matrix-js-sdk 42.3.0 → 42.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/lib/@types/json.d.ts.map +1 -1
- package/lib/@types/json.js.map +1 -1
- package/lib/client.d.ts +74 -5
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +83 -7
- package/lib/client.js.map +1 -1
- package/lib/common-crypto/CryptoBackend.d.ts +42 -23
- package/lib/common-crypto/CryptoBackend.d.ts.map +1 -1
- package/lib/common-crypto/CryptoBackend.js +7 -0
- package/lib/common-crypto/CryptoBackend.js.map +1 -1
- package/lib/embedded.d.ts +35 -1
- package/lib/embedded.d.ts.map +1 -1
- package/lib/embedded.js +49 -1
- package/lib/embedded.js.map +1 -1
- package/lib/http-api/fetch.d.ts +0 -1
- package/lib/http-api/fetch.d.ts.map +1 -1
- package/lib/http-api/fetch.js +3 -22
- package/lib/http-api/fetch.js.map +1 -1
- package/lib/http-api/logging.d.ts +10 -0
- package/lib/http-api/logging.d.ts.map +1 -0
- package/lib/http-api/logging.js +46 -0
- package/lib/http-api/logging.js.map +1 -0
- package/lib/matrixrtc/EncryptionManager.d.ts +5 -0
- package/lib/matrixrtc/EncryptionManager.d.ts.map +1 -1
- package/lib/matrixrtc/EncryptionManager.js.map +1 -1
- package/lib/matrixrtc/LivekitTransport.d.ts +82 -0
- package/lib/matrixrtc/LivekitTransport.d.ts.map +1 -1
- package/lib/matrixrtc/LivekitTransport.js +25 -0
- package/lib/matrixrtc/LivekitTransport.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.d.ts +41 -2
- package/lib/matrixrtc/MatrixRTCSession.d.ts.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.js +59 -1
- package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
- package/lib/matrixrtc/MembershipManager.js +7 -4
- package/lib/matrixrtc/MembershipManager.js.map +1 -1
- package/lib/matrixrtc/RTCEncryptionManager.d.ts +17 -0
- package/lib/matrixrtc/RTCEncryptionManager.d.ts.map +1 -1
- package/lib/matrixrtc/RTCEncryptionManager.js +68 -29
- package/lib/matrixrtc/RTCEncryptionManager.js.map +1 -1
- package/lib/models/room-receipts.d.ts +9 -3
- package/lib/models/room-receipts.d.ts.map +1 -1
- package/lib/models/room-receipts.js +51 -11
- package/lib/models/room-receipts.js.map +1 -1
- package/lib/oauth/authorize.d.ts +7 -2
- package/lib/oauth/authorize.d.ts.map +1 -1
- package/lib/oauth/authorize.js +10 -4
- package/lib/oauth/authorize.js.map +1 -1
- package/lib/oauth/fetch.d.ts +17 -0
- package/lib/oauth/fetch.d.ts.map +1 -0
- package/lib/oauth/fetch.js +47 -0
- package/lib/oauth/fetch.js.map +1 -0
- package/lib/oauth/index.d.ts +15 -2
- package/lib/oauth/index.d.ts.map +1 -1
- package/lib/oauth/index.js +33 -12
- package/lib/oauth/index.js.map +1 -1
- package/lib/rust-crypto/index.d.ts +17 -0
- package/lib/rust-crypto/index.d.ts.map +1 -1
- package/lib/rust-crypto/index.js +4 -2
- package/lib/rust-crypto/index.js.map +1 -1
- package/lib/rust-crypto/rust-crypto.d.ts +6 -26
- package/lib/rust-crypto/rust-crypto.d.ts.map +1 -1
- package/lib/rust-crypto/rust-crypto.js +19 -54
- package/lib/rust-crypto/rust-crypto.js.map +1 -1
- package/lib/sliding-sync-sdk.d.ts.map +1 -1
- package/lib/sliding-sync-sdk.js +65 -27
- package/lib/sliding-sync-sdk.js.map +1 -1
- package/lib/sliding-sync.d.ts +17 -0
- package/lib/sliding-sync.d.ts.map +1 -1
- package/lib/sliding-sync.js +21 -9
- package/lib/sliding-sync.js.map +1 -1
- package/lib/sync.d.ts +9 -1
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js +54 -29
- package/lib/sync.js.map +1 -1
- package/package.json +5 -5
- package/src/@types/json.ts +11 -2
- package/src/client.ts +126 -11
- package/src/common-crypto/CryptoBackend.ts +45 -23
- package/src/embedded.ts +67 -4
- package/src/http-api/fetch.ts +2 -23
- package/src/http-api/logging.ts +46 -0
- package/src/matrixrtc/EncryptionManager.ts +6 -0
- package/src/matrixrtc/LivekitTransport.ts +86 -0
- package/src/matrixrtc/MatrixRTCSession.ts +81 -1
- package/src/matrixrtc/MembershipManager.ts +7 -7
- package/src/matrixrtc/RTCEncryptionManager.ts +80 -31
- package/src/models/room-receipts.ts +54 -10
- package/src/oauth/authorize.ts +10 -2
- package/src/oauth/fetch.ts +54 -0
- package/src/oauth/index.ts +29 -10
- package/src/rust-crypto/index.ts +23 -0
- package/src/rust-crypto/rust-crypto.ts +25 -67
- package/src/sliding-sync-sdk.ts +73 -33
- package/src/sliding-sync.ts +31 -14
- package/src/sync.ts +58 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matrix-js-sdk",
|
|
3
|
-
"version": "42.
|
|
3
|
+
"version": "42.4.0",
|
|
4
4
|
"description": "Matrix Client-Server SDK for Javascript",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@babel/runtime": "^8.0.0",
|
|
41
|
-
"@matrix-org/matrix-sdk-crypto-wasm": "^18.
|
|
41
|
+
"@matrix-org/matrix-sdk-crypto-wasm": "^18.7.0",
|
|
42
42
|
"another-json": "^0.2.0",
|
|
43
43
|
"bs58": "^6.0.0",
|
|
44
|
-
"content-type": "^
|
|
44
|
+
"content-type": "^3.0.0",
|
|
45
45
|
"loglevel": "^1.9.2",
|
|
46
46
|
"matrix-events-sdk": "0.0.1",
|
|
47
|
-
"matrix-widget-api": "^1.
|
|
47
|
+
"matrix-widget-api": "^1.19.0",
|
|
48
48
|
"p-retry": "8",
|
|
49
49
|
"sdp-transform": "^3.0.0",
|
|
50
50
|
"unhomoglyph": "^1.0.6"
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"knip": "^6.0.0",
|
|
80
80
|
"lint-staged": "^17.0.0",
|
|
81
81
|
"matrix-mock-request": "^2.5.0",
|
|
82
|
-
"oxfmt": "^0.
|
|
82
|
+
"oxfmt": "^0.65.0",
|
|
83
83
|
"oxlint": "^1.70.0",
|
|
84
84
|
"oxlint-tsgolint": "^7.0.0",
|
|
85
85
|
"typedoc": "^0.28.1",
|
package/src/@types/json.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
/*
|
|
2
2
|
Copyright 2024 New Vector Ltd.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
6
15
|
*/
|
|
7
16
|
|
|
8
17
|
// Types for JSON and JSON objects, copied from element-web (left in both places as I don't think we
|
package/src/client.ts
CHANGED
|
@@ -245,7 +245,12 @@ import { sha256 } from "./digest.ts";
|
|
|
245
245
|
import { type ValidatedAuthMetadata, OAuth2Error, isValidAuthMetadata } from "./oauth/index.ts";
|
|
246
246
|
import { type EmptyObject } from "./@types/common.ts";
|
|
247
247
|
import { UnsupportedDelayedEventsEndpointError, UnsupportedStickyEventsEndpointError } from "./errors.ts";
|
|
248
|
-
import {
|
|
248
|
+
import {
|
|
249
|
+
type LivekitDelegateDelayedLeaveRequest,
|
|
250
|
+
type LivekitGetTokenRequest,
|
|
251
|
+
type LivekitGetTokenResponse,
|
|
252
|
+
type Transport,
|
|
253
|
+
} from "./matrixrtc/index.ts";
|
|
249
254
|
import { RetentionPolicyService } from "./retentionPolicy.ts";
|
|
250
255
|
import { createRtcTransportsCachedValue } from "./rtcTransportsCachedValue.ts";
|
|
251
256
|
import { createWellKnownCachedValue } from "./wellKnownCachedValue.ts";
|
|
@@ -525,6 +530,10 @@ export interface IStartClientOpts {
|
|
|
525
530
|
/**
|
|
526
531
|
* The number of seconds between polls to /.well-known/matrix/client, undefined to disable.
|
|
527
532
|
* This should be in the order of hours. Default: undefined.
|
|
533
|
+
*
|
|
534
|
+
* When disabled, the client never requests the well-known on its own: nothing is fetched on
|
|
535
|
+
* startup and {@link MatrixClient.getClientWellKnown} stays undefined. Callers that still need
|
|
536
|
+
* it can fetch it on demand via {@link MatrixClient.waitForClientWellKnown}.
|
|
528
537
|
*/
|
|
529
538
|
clientWellKnownPollPeriod?: number;
|
|
530
539
|
|
|
@@ -1518,11 +1527,11 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
1518
1527
|
|
|
1519
1528
|
this.syncApi.sync().catch((e) => this.logger.info("Sync startup aborted with an error:", e));
|
|
1520
1529
|
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1530
|
+
// Only poll the client well-known when a poll period was configured: leaving
|
|
1531
|
+
// `clientWellKnownPollPeriod` undefined disables the lookups entirely.
|
|
1532
|
+
if (this.clientOpts.clientWellKnownPollPeriod !== undefined) {
|
|
1533
|
+
this.cachedWellKnown.start(1000 * this.clientOpts.clientWellKnownPollPeriod);
|
|
1534
|
+
}
|
|
1526
1535
|
|
|
1527
1536
|
this.toDeviceMessageQueue.start();
|
|
1528
1537
|
this.serverCapabilitiesService.start();
|
|
@@ -1980,7 +1989,14 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
1980
1989
|
* @param args.caCertsPem - Optional PEM-formatted string that provides CA certificates. These will be used to check
|
|
1981
1990
|
* X.509 signatures on user identities. Any user identity that has a valid signature according to the supplied
|
|
1982
1991
|
* CAs will be considered verified, without any manual verification taking place.
|
|
1983
|
-
*
|
|
1992
|
+
* NOTE: this is an unspecified extension to Matrix. Applications should exercise caution when using it.
|
|
1993
|
+
* @param args.x509Signer - Optional async function for signing some data with an X.509 certificate. Used to sign
|
|
1994
|
+
* the user's identity so compatible clients will recognise this user as verified without manual verification
|
|
1995
|
+
* taking place. If you supply this you must also supply `x509Validity`.
|
|
1996
|
+
* NOTE: this is an unspecified extension to Matrix. Applications should exercise caution when using it.
|
|
1997
|
+
* @param args.x509Validity - Optional function returning the validity period of the X.509 certificate used for
|
|
1998
|
+
* signing, as the number of milliseconds since the Unix epoch. If you supply this you must also supply
|
|
1999
|
+
* `x509Signer`.
|
|
1984
2000
|
* NOTE: this is an unspecified extension to Matrix. Applications should exercise caution when using it.
|
|
1985
2001
|
*
|
|
1986
2002
|
* @returns a Promise which will resolve when the crypto layer has been
|
|
@@ -1993,6 +2009,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
1993
2009
|
storageKey?: Uint8Array;
|
|
1994
2010
|
storagePassword?: string;
|
|
1995
2011
|
caCertsPem?: string;
|
|
2012
|
+
x509Signer?: (item: Uint8Array) => Promise<{
|
|
2013
|
+
signature_bytes: Uint8Array;
|
|
2014
|
+
certificate_chain: string;
|
|
2015
|
+
signature_scheme: "RsaPssSha512";
|
|
2016
|
+
}>;
|
|
2017
|
+
x509Validity?: () => number;
|
|
1996
2018
|
} = {},
|
|
1997
2019
|
): Promise<void> {
|
|
1998
2020
|
if (this.cryptoBackend) {
|
|
@@ -2040,6 +2062,8 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
2040
2062
|
enableEncryptedStateEvents: this.enableEncryptedStateEvents,
|
|
2041
2063
|
|
|
2042
2064
|
caCertsPem: args.caCertsPem,
|
|
2065
|
+
x509Signer: args.x509Signer,
|
|
2066
|
+
x509Validity: args.x509Validity,
|
|
2043
2067
|
});
|
|
2044
2068
|
|
|
2045
2069
|
rustCrypto.setSupportedVerificationMethods(this.verificationMethods);
|
|
@@ -3607,6 +3631,45 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
3607
3631
|
});
|
|
3608
3632
|
}
|
|
3609
3633
|
|
|
3634
|
+
/**
|
|
3635
|
+
* Get information about a specified delayed event owned by the requesting user.
|
|
3636
|
+
*
|
|
3637
|
+
* Note: This endpoint is unstable, and can throw an `Error`.
|
|
3638
|
+
* Check progress on [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for more details.
|
|
3639
|
+
*/
|
|
3640
|
+
public async _unstable_getDelayedEvent(delayId: string): Promise<{
|
|
3641
|
+
delay_id: string;
|
|
3642
|
+
room_id: string;
|
|
3643
|
+
type: string;
|
|
3644
|
+
state_key?: string;
|
|
3645
|
+
delay_ms: number;
|
|
3646
|
+
delayed_since_ts: number;
|
|
3647
|
+
content: IContent;
|
|
3648
|
+
finalised?: {
|
|
3649
|
+
error?: MatrixError["data"];
|
|
3650
|
+
event_id?: string;
|
|
3651
|
+
finalised_ts: number;
|
|
3652
|
+
};
|
|
3653
|
+
}> {
|
|
3654
|
+
// TODO: define a type/interface for the return shape once MSC4140 has become stable
|
|
3655
|
+
if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
|
|
3656
|
+
throw new UnsupportedDelayedEventsEndpointError(
|
|
3657
|
+
"Server does not support the delayed events API",
|
|
3658
|
+
"getDelayedEvents",
|
|
3659
|
+
);
|
|
3660
|
+
}
|
|
3661
|
+
|
|
3662
|
+
return await this.http.authedRequest(
|
|
3663
|
+
Method.Get,
|
|
3664
|
+
utils.encodeUri("/delayed_events/$delayId", { $delayId: delayId }),
|
|
3665
|
+
undefined,
|
|
3666
|
+
undefined,
|
|
3667
|
+
{
|
|
3668
|
+
prefix: `${ClientPrefix.Unstable}/${UNSTABLE_MSC4140_DELAYED_EVENTS}`,
|
|
3669
|
+
},
|
|
3670
|
+
);
|
|
3671
|
+
}
|
|
3672
|
+
|
|
3610
3673
|
/**
|
|
3611
3674
|
* Get information about delayed events owned by the requesting user.
|
|
3612
3675
|
*
|
|
@@ -6181,6 +6244,58 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
6181
6244
|
).rtc_transports;
|
|
6182
6245
|
}
|
|
6183
6246
|
|
|
6247
|
+
/**
|
|
6248
|
+
* Requests a token to authenticate against a LiveKit SFU with (MSC4195).
|
|
6249
|
+
*
|
|
6250
|
+
* The homeserver checks that we are joined to `room_id` before obtaining a token from the SFU. If
|
|
6251
|
+
* `server_name` names a remote homeserver, our homeserver forwards the request to it over federation,
|
|
6252
|
+
* which is how a token for another homeserver's SFU is obtained.
|
|
6253
|
+
*
|
|
6254
|
+
* Requires homeserver support for MSC4195.
|
|
6255
|
+
*
|
|
6256
|
+
* @param body - The details of the `m.rtc.member` event to obtain a token for, and the SFU to obtain it from.
|
|
6257
|
+
* @returns The JWT to authenticate with when connecting to the SFU.
|
|
6258
|
+
* @throws A M_NOT_FOUND error if not supported by the homeserver, a M_FORBIDDEN error if we (or, when
|
|
6259
|
+
* federating, our homeserver) are not joined to the room, or a M_INVALID_PARAM error if `url` is not one
|
|
6260
|
+
* of the answering server's SFUs.
|
|
6261
|
+
*/
|
|
6262
|
+
public async _unstable_getLivekitToken(body: LivekitGetTokenRequest): Promise<LivekitGetTokenResponse> {
|
|
6263
|
+
// There is no /versions flag to check for support, so we just have to attempt a request.
|
|
6264
|
+
return await this.http.authedRequest<LivekitGetTokenResponse>(
|
|
6265
|
+
Method.Post,
|
|
6266
|
+
"/rtc/livekit/get_token",
|
|
6267
|
+
undefined,
|
|
6268
|
+
body,
|
|
6269
|
+
{ prefix: `${ClientPrefix.Unstable}/io.element.msc4195` },
|
|
6270
|
+
);
|
|
6271
|
+
}
|
|
6272
|
+
|
|
6273
|
+
/**
|
|
6274
|
+
* Hands over the management of a delayed MatrixRTC leave event to the homeserver (MSC4195).
|
|
6275
|
+
*
|
|
6276
|
+
* The homeserver restarts the delayed event for as long as it observes our connection to the SFU, and
|
|
6277
|
+
* sends it once we disconnect, so the client does not have to restart it itself. This is more reliable
|
|
6278
|
+
* than client-side restarts under poor network conditions.
|
|
6279
|
+
*
|
|
6280
|
+
* large timeouts are recommended for delayed delegation (in the range of hours)
|
|
6281
|
+
* Requires homeserver support for MSC4195.
|
|
6282
|
+
*
|
|
6283
|
+
* @param body - The details of the `m.rtc.member` event and the delayed leave event to delegate, and the SFU
|
|
6284
|
+
* we are connected to.
|
|
6285
|
+
* @throws A M_NOT_FOUND error if not supported by the homeserver, a M_BAD_JSON error if the delayed
|
|
6286
|
+
* event's timeout is below one hour, or a M_INVALID_PARAM error if `url` is not one of the homeserver's SFUs.
|
|
6287
|
+
*/
|
|
6288
|
+
public async _unstable_delegateDelayedLeave(body: LivekitDelegateDelayedLeaveRequest): Promise<EmptyObject> {
|
|
6289
|
+
// There is no /versions flag to check for support, so we just have to attempt a request.
|
|
6290
|
+
return await this.http.authedRequest<EmptyObject>(
|
|
6291
|
+
Method.Post,
|
|
6292
|
+
"/rtc/livekit/delegate_delayed_leave",
|
|
6293
|
+
undefined,
|
|
6294
|
+
body,
|
|
6295
|
+
{ prefix: `${ClientPrefix.Unstable}/io.element.msc4195` },
|
|
6296
|
+
);
|
|
6297
|
+
}
|
|
6298
|
+
|
|
6184
6299
|
/**
|
|
6185
6300
|
* Get the API versions supported by the server, along with any
|
|
6186
6301
|
* unstable APIs it supports
|
|
@@ -6907,7 +7022,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
6907
7022
|
/**
|
|
6908
7023
|
* @param includeMembership - the membership type to include in the response
|
|
6909
7024
|
* @param excludeMembership - the membership type to exclude from the response
|
|
6910
|
-
* @param
|
|
7025
|
+
* @param atSyncToken - the point in time, as a sync pagination token, for when the members should be returned for
|
|
6911
7026
|
* @returns Promise which resolves: dictionary of userid to profile information
|
|
6912
7027
|
* @returns Rejects: with an error response.
|
|
6913
7028
|
*/
|
|
@@ -6915,7 +7030,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
6915
7030
|
roomId: string,
|
|
6916
7031
|
includeMembership?: string,
|
|
6917
7032
|
excludeMembership?: string,
|
|
6918
|
-
|
|
7033
|
+
atSyncToken?: string,
|
|
6919
7034
|
): Promise<{ [userId: string]: IStateEventWithRoomId[] }> {
|
|
6920
7035
|
const queryParams: Record<string, string> = {};
|
|
6921
7036
|
if (includeMembership) {
|
|
@@ -6924,8 +7039,8 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
6924
7039
|
if (excludeMembership) {
|
|
6925
7040
|
queryParams.not_membership = excludeMembership;
|
|
6926
7041
|
}
|
|
6927
|
-
if (
|
|
6928
|
-
queryParams.at =
|
|
7042
|
+
if (atSyncToken) {
|
|
7043
|
+
queryParams.at = atSyncToken;
|
|
6929
7044
|
}
|
|
6930
7045
|
|
|
6931
7046
|
const queryString = utils.encodeParams(queryParams);
|
|
@@ -118,42 +118,64 @@ export interface CryptoBackend extends SyncCryptoCallbacks, CryptoApi {
|
|
|
118
118
|
markRoomAsPendingKeyBundle(roomId: string, inviterId: string): Promise<void>;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* The parts of a sync response which are relevant to encryption, as passed to
|
|
123
|
+
* {@link SyncCryptoCallbacks.processSyncChanges}.
|
|
122
124
|
*
|
|
123
125
|
* @internal
|
|
124
126
|
*/
|
|
125
|
-
export interface
|
|
127
|
+
export interface SyncCryptoChanges {
|
|
128
|
+
/** The to-device events from the sync response (`to_device.events`), or an empty list if there were none. */
|
|
129
|
+
toDeviceEvents: IToDeviceEvent[];
|
|
130
|
+
|
|
131
|
+
/** The `device_lists` field from the sync response, if any. */
|
|
132
|
+
deviceLists?: IDeviceLists;
|
|
133
|
+
|
|
126
134
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* The implementation may preprocess the received messages (eg, decrypt them) and return an
|
|
130
|
-
* updated list of messages for dispatch to the rest of the system.
|
|
131
|
-
*
|
|
132
|
-
* Note that, unlike {@link ClientEvent.ToDeviceEvent} events, this is called on the raw to-device
|
|
133
|
-
* messages, rather than the results of any decryption attempts.
|
|
134
|
-
*
|
|
135
|
-
* @param events - the received to-device messages
|
|
136
|
-
* @returns A list of preprocessed to-device messages. This will not map 1:1 to the input list, as some messages may be invalid or
|
|
137
|
-
* failed to decrypt, and so will be omitted from the output list.
|
|
135
|
+
* The `device_one_time_keys_count` field from the sync response, if any.
|
|
138
136
|
*
|
|
137
|
+
* The meaning of an algorithm missing from the map (or of an absent field) depends on {@link useMsc4186}: in
|
|
138
|
+
* sync v2 it means that there are no one-time keys of that algorithm on the server; in sliding sync it means that
|
|
139
|
+
* the count is unchanged since the previous response.
|
|
139
140
|
*/
|
|
140
|
-
|
|
141
|
+
oneTimeKeysCounts?: Record<string, number>;
|
|
141
142
|
|
|
142
143
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
* The `device_unused_fallback_key_types` field from the sync response, or `undefined` if the response did not
|
|
145
|
+
* include it (which means that the server does not support fallback keys).
|
|
146
|
+
*/
|
|
147
|
+
unusedFallbackKeys?: string[];
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Whether to interpret the response with MSC4186 (simplified sliding sync) semantics rather than sync v2. This
|
|
151
|
+
* selects the meaning of missing one-time key counts: see {@link oneTimeKeysCounts}. Defaults to `false`.
|
|
147
152
|
*/
|
|
148
|
-
|
|
153
|
+
useMsc4186?: boolean;
|
|
154
|
+
}
|
|
149
155
|
|
|
156
|
+
/** The methods which crypto implementations should expose to the Sync api
|
|
157
|
+
*
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
export interface SyncCryptoCallbacks {
|
|
150
161
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
162
|
+
* Called by the sync loop once per sync response, with the parts of the response which are relevant to
|
|
163
|
+
* encryption: to-device messages, device list changes, one-time key counts and unused fallback key types.
|
|
164
|
+
*
|
|
165
|
+
* All of this data must be passed together, in a single call per sync response, because the OlmMachine
|
|
166
|
+
* interprets it as the complete E2EE state from a sync response. In particular, per the sync v2 specification,
|
|
167
|
+
* an absent `device_one_time_keys_count` means that there are no one-time keys on the server, so calling this
|
|
168
|
+
* without the counts from the response would trigger a spurious one-time key upload. (Sliding sync responses
|
|
169
|
+
* omit the count when it is unchanged; {@link SyncCryptoChanges.useMsc4186} selects that interpretation.)
|
|
170
|
+
*
|
|
171
|
+
* This must be called before the room events in the sync response are processed, so that any room keys received
|
|
172
|
+
* in to-device messages are available when decrypting room events.
|
|
153
173
|
*
|
|
154
|
-
* @param
|
|
174
|
+
* @param changes - the E2EE-relevant parts of the sync response
|
|
175
|
+
* @returns A list of processed to-device messages. This will not map 1:1 to the input list, as some messages may
|
|
176
|
+
* be invalid or fail to decrypt, and so will be omitted from the output list.
|
|
155
177
|
*/
|
|
156
|
-
|
|
178
|
+
processSyncChanges(changes: SyncCryptoChanges): Promise<ReceivedToDeviceMessage[]>;
|
|
157
179
|
|
|
158
180
|
/**
|
|
159
181
|
* Called by the /sync loop whenever an m.room.encryption event is received.
|
package/src/embedded.ts
CHANGED
|
@@ -32,7 +32,12 @@ import {
|
|
|
32
32
|
UnstableApiVersion,
|
|
33
33
|
} from "matrix-widget-api";
|
|
34
34
|
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
type LivekitDelegateDelayedLeaveRequest,
|
|
37
|
+
type LivekitGetTokenRequest,
|
|
38
|
+
type LivekitGetTokenResponse,
|
|
39
|
+
type Transport,
|
|
40
|
+
} from "./matrixrtc/index.ts";
|
|
36
41
|
import { MatrixEvent, type IEvent, EventStatus } from "./models/event.ts";
|
|
37
42
|
import {
|
|
38
43
|
type ISendEventResponse,
|
|
@@ -145,6 +150,21 @@ export interface ICapabilities {
|
|
|
145
150
|
* @defaultValue false
|
|
146
151
|
*/
|
|
147
152
|
rtcTransports?: boolean;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Whether this client needs to be able to obtain LiveKit SFU tokens through the host.
|
|
156
|
+
* @experimental Part of MSC4195 & MSC4533
|
|
157
|
+
* @defaultValue false
|
|
158
|
+
*/
|
|
159
|
+
rtcLivekitGetToken?: boolean;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Whether this client needs to be able to hand delayed MatrixRTC leave events over to the
|
|
163
|
+
* homeserver through the host.
|
|
164
|
+
* @experimental Part of MSC4195 & MSC4533
|
|
165
|
+
* @defaultValue false
|
|
166
|
+
*/
|
|
167
|
+
rtcLivekitDelegateDelayedLeave?: boolean;
|
|
148
168
|
}
|
|
149
169
|
|
|
150
170
|
export enum RoomWidgetClientEvent {
|
|
@@ -296,6 +316,12 @@ export class RoomWidgetClient extends MatrixClient {
|
|
|
296
316
|
if (capabilities.rtcTransports) {
|
|
297
317
|
this.widgetApi.requestCapability(MatrixCapabilities.MSC4515RtcTransports);
|
|
298
318
|
}
|
|
319
|
+
if (capabilities.rtcLivekitGetToken) {
|
|
320
|
+
this.widgetApi.requestCapability(MatrixCapabilities.MSC4533RtcLivekitGetToken);
|
|
321
|
+
}
|
|
322
|
+
if (capabilities.rtcLivekitDelegateDelayedLeave) {
|
|
323
|
+
this.widgetApi.requestCapability(MatrixCapabilities.MSC4533RtcLivekitDelegateDelayedLeave);
|
|
324
|
+
}
|
|
299
325
|
}
|
|
300
326
|
|
|
301
327
|
public async supportUpdateState(): Promise<boolean> {
|
|
@@ -357,9 +383,11 @@ export class RoomWidgetClient extends MatrixClient {
|
|
|
357
383
|
);
|
|
358
384
|
}
|
|
359
385
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
)
|
|
386
|
+
// Only poll the client well-known when a poll period was configured: leaving
|
|
387
|
+
// `clientWellKnownPollPeriod` undefined disables the lookups entirely.
|
|
388
|
+
if (opts.clientWellKnownPollPeriod !== undefined) {
|
|
389
|
+
this.cachedWellKnown.start(1000 * opts.clientWellKnownPollPeriod);
|
|
390
|
+
}
|
|
363
391
|
this.setSyncState(SyncState.Syncing);
|
|
364
392
|
logger.info("Finished initial sync");
|
|
365
393
|
|
|
@@ -645,6 +673,41 @@ export class RoomWidgetClient extends MatrixClient {
|
|
|
645
673
|
return rtcTransports;
|
|
646
674
|
}
|
|
647
675
|
|
|
676
|
+
/**
|
|
677
|
+
* Requests a token to authenticate against a LiveKit SFU with.
|
|
678
|
+
*
|
|
679
|
+
* Overrides the homeserver-side {@link MatrixClient._unstable_getLivekitToken} (MSC4195): a widget
|
|
680
|
+
* cannot make authenticated homeserver calls itself, so we ask the host to make the call on our
|
|
681
|
+
* behalf over the widget API instead (MSC4533). Requires the `rtcLivekitGetToken` capability and a
|
|
682
|
+
* host that advertises the `org.matrix.msc4533` API version (otherwise the request throws).
|
|
683
|
+
*
|
|
684
|
+
* `server_name` defaults to our own homeserver, matching what the endpoint would do server-side.
|
|
685
|
+
*/
|
|
686
|
+
public override async _unstable_getLivekitToken(body: LivekitGetTokenRequest): Promise<LivekitGetTokenResponse> {
|
|
687
|
+
const serverName = body.server_name ?? this.getDomain();
|
|
688
|
+
if (serverName === null) throw new Error("Cannot determine the server name to request a token from");
|
|
689
|
+
const { jwt } = await this.widgetApi
|
|
690
|
+
.getRtcLivekitToken({ ...body, server_name: serverName })
|
|
691
|
+
.catch(timeoutToConnectionError);
|
|
692
|
+
return { jwt };
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Hands over the management of a delayed MatrixRTC leave event to the homeserver.
|
|
697
|
+
*
|
|
698
|
+
* Overrides the homeserver-side {@link MatrixClient._unstable_delegateDelayedLeave} (MSC4195): a
|
|
699
|
+
* widget cannot make authenticated homeserver calls itself, so we ask the host to make the call on
|
|
700
|
+
* our behalf over the widget API instead (MSC4533). Requires the `rtcLivekitDelegateDelayedLeave`
|
|
701
|
+
* capability and a host that advertises the `org.matrix.msc4533` API version (otherwise the request
|
|
702
|
+
* throws).
|
|
703
|
+
*/
|
|
704
|
+
public override async _unstable_delegateDelayedLeave(
|
|
705
|
+
body: LivekitDelegateDelayedLeaveRequest,
|
|
706
|
+
): Promise<EmptyObject> {
|
|
707
|
+
await this.widgetApi.delegateRtcLivekitDelayedLeave(body).catch(timeoutToConnectionError);
|
|
708
|
+
return {};
|
|
709
|
+
}
|
|
710
|
+
|
|
648
711
|
public async queueToDevice({ eventType, batch }: ToDeviceBatch): Promise<void> {
|
|
649
712
|
// map: user Id → device Id → payload
|
|
650
713
|
const contentMap: MapWithDefault<string, Map<string, ToDevicePayload>> = new MapWithDefault(() => new Map());
|
package/src/http-api/fetch.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
type Body,
|
|
32
32
|
} from "./interface.ts";
|
|
33
33
|
import { anySignal, parseErrorResponse, timeoutSignal } from "./utils.ts";
|
|
34
|
+
import { sanitizeUrlForLogs } from "./logging.ts";
|
|
34
35
|
import { type QueryDict } from "../utils.ts";
|
|
35
36
|
import { TokenRefresher, TokenRefreshOutcome } from "./refresh.ts";
|
|
36
37
|
|
|
@@ -241,7 +242,7 @@ export class FetchHttpApi<O extends IHttpOpts> {
|
|
|
241
242
|
throw new Error("Invalid call to `FetchHttpApi` sets both `opts.json` and `opts.rawResponseBody`");
|
|
242
243
|
}
|
|
243
244
|
|
|
244
|
-
const urlForLogs =
|
|
245
|
+
const urlForLogs = sanitizeUrlForLogs(url);
|
|
245
246
|
|
|
246
247
|
this.opts.logger?.debug(`FetchHttpApi: --> ${method} ${urlForLogs}`);
|
|
247
248
|
|
|
@@ -330,28 +331,6 @@ export class FetchHttpApi<O extends IHttpOpts> {
|
|
|
330
331
|
}
|
|
331
332
|
}
|
|
332
333
|
|
|
333
|
-
private sanitizeUrlForLogs(url: URL | string): string {
|
|
334
|
-
try {
|
|
335
|
-
let asUrl: URL;
|
|
336
|
-
if (typeof url === "string") {
|
|
337
|
-
asUrl = new URL(url);
|
|
338
|
-
} else {
|
|
339
|
-
asUrl = url;
|
|
340
|
-
}
|
|
341
|
-
// Remove the values of any URL params that could contain potential secrets
|
|
342
|
-
const sanitizedQs = new URLSearchParams();
|
|
343
|
-
for (const key of asUrl.searchParams.keys()) {
|
|
344
|
-
sanitizedQs.append(key, "xxx");
|
|
345
|
-
}
|
|
346
|
-
const sanitizedQsString = sanitizedQs.toString();
|
|
347
|
-
const sanitizedQsUrlPiece = sanitizedQsString ? `?${sanitizedQsString}` : "";
|
|
348
|
-
|
|
349
|
-
return asUrl.origin + asUrl.pathname + sanitizedQsUrlPiece;
|
|
350
|
-
} catch {
|
|
351
|
-
// defensive coding for malformed url
|
|
352
|
-
return "??";
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
334
|
/**
|
|
356
335
|
* Form and return a homeserver request URL based on the given path params and prefix.
|
|
357
336
|
* @param path - The HTTP path <b>after</b> the supplied prefix e.g. "/createRoom".
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2026 The Matrix.org Foundation C.I.C.
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Produce a version of the given URL which is safe to write to logs, by redacting the values of any query parameters,
|
|
19
|
+
* as they may contain secrets.
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
* @param url - the URL to sanitize.
|
|
23
|
+
* @returns the sanitized URL, or `"??"` if the URL could not be parsed.
|
|
24
|
+
*/
|
|
25
|
+
export function sanitizeUrlForLogs(url: URL | string): string {
|
|
26
|
+
try {
|
|
27
|
+
let asUrl: URL;
|
|
28
|
+
if (typeof url === "string") {
|
|
29
|
+
asUrl = new URL(url);
|
|
30
|
+
} else {
|
|
31
|
+
asUrl = url;
|
|
32
|
+
}
|
|
33
|
+
// Remove the values of any URL params that could contain potential secrets
|
|
34
|
+
const sanitizedQs = new URLSearchParams();
|
|
35
|
+
for (const key of asUrl.searchParams.keys()) {
|
|
36
|
+
sanitizedQs.append(key, "xxx");
|
|
37
|
+
}
|
|
38
|
+
const sanitizedQsString = sanitizedQs.toString();
|
|
39
|
+
const sanitizedQsUrlPiece = sanitizedQsString ? `?${sanitizedQsString}` : "";
|
|
40
|
+
|
|
41
|
+
return asUrl.origin + asUrl.pathname + sanitizedQsUrlPiece;
|
|
42
|
+
} catch {
|
|
43
|
+
// defensive coding for malformed url
|
|
44
|
+
return "??";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -15,6 +15,12 @@ export function getEncryptionKeyMapKey(membership: CallMembershipIdentityParts):
|
|
|
15
15
|
* @internal
|
|
16
16
|
*/
|
|
17
17
|
export interface IEncryptionManager {
|
|
18
|
+
/**
|
|
19
|
+
* Whether the key rotation is currently halted.
|
|
20
|
+
* @see EncryptionConfig.keyRotationParticipantLimit
|
|
21
|
+
*/
|
|
22
|
+
readonly isKeyRotationSuppressed: boolean;
|
|
23
|
+
|
|
18
24
|
/**
|
|
19
25
|
* Joins the encryption manager with the provided configuration.
|
|
20
26
|
*
|
|
@@ -44,3 +44,89 @@ export interface LivekitFocusSelection extends Transport {
|
|
|
44
44
|
*/
|
|
45
45
|
export const isLivekitFocusSelection = (object: any): object is LivekitFocusSelection =>
|
|
46
46
|
object.type === "livekit" && "focus_selection" in object;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Identifies the MatrixRTC membership that a LiveKit request is made for (MSC4195).
|
|
50
|
+
*
|
|
51
|
+
* Note that this is *not* the `member` field of an `m.rtc.member` event verbatim: the homeserver knows
|
|
52
|
+
* the user ID from the access token, and the device ID is only ever claimed, never verified.
|
|
53
|
+
*/
|
|
54
|
+
export interface LivekitRtcMember {
|
|
55
|
+
/**
|
|
56
|
+
* The ID of the member within the MatrixRTC session, i.e. the `member.id` of the `m.rtc.member` event.
|
|
57
|
+
*/
|
|
58
|
+
id: string;
|
|
59
|
+
/**
|
|
60
|
+
* The device ID the member claims to be using, i.e. the `member.device_id` of the `m.rtc.member` event.
|
|
61
|
+
*/
|
|
62
|
+
claimed_device_id?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The body of a request to the LiveKit `get_token` endpoint (MSC4195).
|
|
67
|
+
*
|
|
68
|
+
* Declared as a type alias rather than an interface so that it can be passed to the widget API
|
|
69
|
+
* (MSC4533), which expects request data to be assignable to an index signature.
|
|
70
|
+
*/
|
|
71
|
+
export type LivekitGetTokenRequest = {
|
|
72
|
+
/**
|
|
73
|
+
* The WebSocket URL of the LiveKit SFU to obtain a token for.
|
|
74
|
+
*/
|
|
75
|
+
url: string;
|
|
76
|
+
/**
|
|
77
|
+
* The room ID of the Matrix room the `m.rtc.member` event is in.
|
|
78
|
+
*/
|
|
79
|
+
room_id: string;
|
|
80
|
+
/**
|
|
81
|
+
* The slot ID from the `m.rtc.member` event.
|
|
82
|
+
*/
|
|
83
|
+
slot_id: string;
|
|
84
|
+
/**
|
|
85
|
+
* The MatrixRTC membership to obtain a token for.
|
|
86
|
+
*/
|
|
87
|
+
member: LivekitRtcMember;
|
|
88
|
+
/**
|
|
89
|
+
* The server name of the `m.rtc.member` event's sender. If omitted, the homeserver uses its own
|
|
90
|
+
* server name. This is what makes it possible to obtain a token for an SFU of a remote homeserver.
|
|
91
|
+
*/
|
|
92
|
+
server_name?: string;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The response of the LiveKit `get_token` endpoint (MSC4195).
|
|
97
|
+
*/
|
|
98
|
+
export interface LivekitGetTokenResponse {
|
|
99
|
+
/**
|
|
100
|
+
* The JWT to authenticate with when connecting to the SFU.
|
|
101
|
+
*/
|
|
102
|
+
jwt: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The body of a request to the LiveKit `delegate_delayed_leave` endpoint (MSC4195).
|
|
107
|
+
*
|
|
108
|
+
* Declared as a type alias rather than an interface so that it can be passed to the widget API
|
|
109
|
+
* (MSC4533), which expects request data to be assignable to an index signature.
|
|
110
|
+
*/
|
|
111
|
+
export type LivekitDelegateDelayedLeaveRequest = {
|
|
112
|
+
/**
|
|
113
|
+
* The WebSocket URL of the LiveKit SFU that we are connected to.
|
|
114
|
+
*/
|
|
115
|
+
url: string;
|
|
116
|
+
/**
|
|
117
|
+
* The room ID of the Matrix room the `m.rtc.member` event is in.
|
|
118
|
+
*/
|
|
119
|
+
room_id: string;
|
|
120
|
+
/**
|
|
121
|
+
* The slot ID from the `m.rtc.member` event.
|
|
122
|
+
*/
|
|
123
|
+
slot_id: string;
|
|
124
|
+
/**
|
|
125
|
+
* The MatrixRTC membership the delayed leave event belongs to.
|
|
126
|
+
*/
|
|
127
|
+
member: LivekitRtcMember;
|
|
128
|
+
/**
|
|
129
|
+
* The delay ID of the delayed leave event to hand over to the homeserver.
|
|
130
|
+
*/
|
|
131
|
+
delay_id: string;
|
|
132
|
+
};
|