Add matrix_rtc_mode config option (#4014)

* Move MatrixRTCMode enum from settings.ts to ConfigOptions.ts

* Add matrix_rtc_mode config option

* add matrix_rtc_mode to config.sample.json

* Update src/settings/DeveloperSettingsTab.tsx

Co-authored-by: Johannes Marbach <n0-0ne+github@mailbox.org>

* Update src/settings/DeveloperSettingsTab.test.tsx

Co-authored-by: Johannes Marbach <n0-0ne+github@mailbox.org>

* reviewer comments

---------

Co-authored-by: Johannes Marbach <n0-0ne+github@mailbox.org>
This commit is contained in:
fkwp
2026-06-05 11:49:43 +02:00
committed by GitHub
parent 3a6579f78d
commit b99c8821d3
14 changed files with 236 additions and 26 deletions

54
src/config/Config.test.ts Normal file
View File

@@ -0,0 +1,54 @@
/*
Copyright 2026 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { describe, expect, it, vi, afterEach } from "vitest";
import { logger } from "matrix-js-sdk/lib/logger";
import { validateConfig } from "./Config";
import { MatrixRTCMode } from "./ConfigOptions";
describe("validateConfig", () => {
afterEach(() => {
vi.restoreAllMocks();
});
it("passes through a missing matrix_rtc_mode unchanged", () => {
const result = validateConfig({});
expect(result.matrix_rtc_mode).toBeUndefined();
});
it.each(Object.values(MatrixRTCMode))(
"keeps a valid matrix_rtc_mode value (%s)",
(mode) => {
const warnSpy = vi.spyOn(logger, "warn").mockImplementation(() => {});
const result = validateConfig({ matrix_rtc_mode: mode });
expect(result.matrix_rtc_mode).toBe(mode);
expect(warnSpy).not.toHaveBeenCalled();
},
);
it("drops an invalid matrix_rtc_mode value and warns", () => {
const warnSpy = vi.spyOn(logger, "warn").mockImplementation(() => {});
const result = validateConfig({
// Intentionally bypass the type to simulate bad JSON.
matrix_rtc_mode: "nonsense" as unknown as MatrixRTCMode,
});
expect(result.matrix_rtc_mode).toBeUndefined();
expect(warnSpy).toHaveBeenCalledTimes(1);
expect(warnSpy.mock.calls[0][0]).toContain("nonsense");
});
it("does not touch unrelated fields when dropping an invalid mode", () => {
vi.spyOn(logger, "warn").mockImplementation(() => {});
const result = validateConfig({
matrix_rtc_mode: "nope" as unknown as MatrixRTCMode,
ssla: "https://example.invalid/ssla",
});
expect(result.matrix_rtc_mode).toBeUndefined();
expect(result.ssla).toBe("https://example.invalid/ssla");
});
});

View File

@@ -6,6 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import { merge } from "lodash-es";
import { logger } from "matrix-js-sdk/lib/logger";
import { getUrlParams } from "../UrlParams";
import {
@@ -14,6 +15,11 @@ import {
type ResolvedConfigOptions,
} from "./ConfigOptions";
import { isFailure } from "../utils/fetch";
import { MatrixRTCMode } from "./ConfigOptions";
const VALID_MATRIX_RTC_MODES: ReadonlySet<string> = new Set(
Object.values(MatrixRTCMode),
);
export class Config {
private static internalInstance: Config | undefined;
@@ -44,7 +50,11 @@ export class Config {
Config.internalInstance.initPromise = downloadConfig(fetchTarget).then(
(config) => {
internalInstance.config = merge({}, DEFAULT_CONFIG, config);
internalInstance.config = merge(
{},
DEFAULT_CONFIG,
validateConfig(config),
);
},
);
}
@@ -84,6 +94,17 @@ export class Config {
private initPromise?: Promise<void>;
}
export function validateConfig(config: ConfigOptions): ConfigOptions {
const mode = config.matrix_rtc_mode;
if (mode !== undefined && !VALID_MATRIX_RTC_MODES.has(mode)) {
logger.warn(
`Ignoring invalid matrix_rtc_mode in config.json: ${String(mode)}`,
);
delete config.matrix_rtc_mode;
}
return config;
}
async function downloadConfig(fetchTarget: string): Promise<ConfigOptions> {
const response = await fetch(fetchTarget);

View File

@@ -6,6 +6,26 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
/**
* The MatrixRTC mode determines how Element Call interacts with the
* MatrixRTC backend and other participants. Selectable via the Developer
* Settings, or pinned for a deployment via `matrix_rtc_mode` in config.json.
*/
export enum MatrixRTCMode {
/** Legacy single-SFU + user-keyed memberships + legacy JWT endpoint. */
Legacy = "legacy",
/** Multi-SFU transport, legacy JWT endpoint, no sticky events. */
Compatibility = "compatibility",
/**
* Multi-SFU transport with:
* - sticky events
* - hashed RTC backend identity
* - the new endpoint for the jwt token on the local membership (remote memberships will always try the new jwt endpoint first -> then the legacy one)
* - use the hashed identity for the local membership
*/
Matrix_2_0 = "matrix_2_0",
}
export interface ConfigOptions {
/**
* The Posthog endpoint to which analytics data will be sent.
@@ -104,6 +124,13 @@ export interface ConfigOptions {
*/
sync_disconnect_grace_period_ms?: number;
/**
* Pins the {@link MatrixRTCMode} for all clients on this deployment,
* overriding any per-user choice from the Developer Settings. If unset,
* the user's Developer Settings choice (or its default of `Legacy`) wins.
*/
matrix_rtc_mode?: MatrixRTCMode;
/**
* These are low level options that are used to configure the MatrixRTC session.
* Take care when changing these options.