Compare commits
34 Commits
v32.1.0-rc.0
...
v32.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 22865fd834 | |||
| abc9911e95 | |||
| efdae0d66f | |||
| 2bf554761c | |||
| c2687643b5 | |||
| a33758eda6 | |||
| 8faed02cc5 | |||
| 3ae0dab47a | |||
| 95394e4cbe | |||
| 8c9bbc01fc | |||
| eb888791a3 | |||
| 6c0b2f55e1 | |||
| c9a5eaece3 | |||
| 64505de36b | |||
| 65d858f9a3 | |||
| 1da5e8f56a | |||
| 5efd4c2915 | |||
| bc03950f8a | |||
| c09da9a23f | |||
| e874468ba3 | |||
| 6fedda91f9 | |||
| d22a39f5d7 | |||
| 4fc6ba884e | |||
| c30e498013 | |||
| 8240bf0ae7 | |||
| 2321c44687 | |||
| 0137e9d5a8 | |||
| 28bbc51752 | |||
| 0db3ac9b43 | |||
| 53039b78ee | |||
| 2a06d19431 | |||
| a747eef04c | |||
| 583823c2ef | |||
| 26d13c15c3 |
@@ -22,7 +22,7 @@ runs:
|
||||
|
||||
- name: Upload tarball signature
|
||||
if: ${{ inputs.upload-url }}
|
||||
uses: shogo82148/actions-upload-release-asset@5bd52f05dd8076794da5975d4c0a4f3bce7dd8f5 # v1
|
||||
uses: shogo82148/actions-upload-release-asset@8f032eff0255912cc9c8455797fd6d72f25c7ab7 # v1
|
||||
with:
|
||||
upload_url: ${{ inputs.upload-url }}
|
||||
asset_path: ${{ env.VERSION }}.tar.gz.asc
|
||||
|
||||
@@ -29,13 +29,13 @@ runs:
|
||||
|
||||
- name: Upload asset signatures
|
||||
if: inputs.gpg-fingerprint
|
||||
uses: shogo82148/actions-upload-release-asset@5bd52f05dd8076794da5975d4c0a4f3bce7dd8f5 # v1
|
||||
uses: shogo82148/actions-upload-release-asset@8f032eff0255912cc9c8455797fd6d72f25c7ab7 # v1
|
||||
with:
|
||||
upload_url: ${{ inputs.upload-url }}
|
||||
asset_path: ${{ inputs.asset-path }}.asc
|
||||
|
||||
- name: Upload assets
|
||||
uses: shogo82148/actions-upload-release-asset@5bd52f05dd8076794da5975d4c0a4f3bce7dd8f5 # v1
|
||||
uses: shogo82148/actions-upload-release-asset@8f032eff0255912cc9c8455797fd6d72f25c7ab7 # v1
|
||||
with:
|
||||
upload_url: ${{ inputs.upload-url }}
|
||||
asset_path: ${{ inputs.asset-path }}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
name: Build downstream artifacts
|
||||
on:
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
|
||||
pull_request: {}
|
||||
|
||||
# For now at least, we don't run this or the downstream-end-to-end-tests against pushes
|
||||
# to develop or master.
|
||||
#
|
||||
#push:
|
||||
# branches: [develop, master]
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build-element-web:
|
||||
name: Build element-web
|
||||
uses: matrix-org/matrix-react-sdk/.github/workflows/element-web.yaml@v3.96.1
|
||||
with:
|
||||
matrix-js-sdk-sha: ${{ github.sha }}
|
||||
react-sdk-repository: matrix-org/matrix-react-sdk
|
||||
@@ -3,10 +3,16 @@
|
||||
|
||||
name: matrix-react-sdk End to End Tests
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Build downstream artifacts"]
|
||||
types:
|
||||
- completed
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
|
||||
pull_request: {}
|
||||
|
||||
# For now at least, we don't run this or the downstream-end-to-end-tests against pushes
|
||||
# to develop or master.
|
||||
#
|
||||
#push:
|
||||
# branches: [develop, master]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.run_id }}
|
||||
@@ -15,44 +21,13 @@ concurrency:
|
||||
jobs:
|
||||
playwright:
|
||||
name: Playwright
|
||||
# We only want to run the playwright tests on merge queue to prevent regressions
|
||||
# from creeping in. They take a long time to run and consume multiple concurrent runners.
|
||||
if: github.event.workflow_run.event == 'merge_group'
|
||||
uses: matrix-org/matrix-react-sdk/.github/workflows/end-to-end-tests.yaml@develop
|
||||
permissions:
|
||||
actions: read
|
||||
issues: read
|
||||
statuses: write
|
||||
pull-requests: read
|
||||
deployments: write
|
||||
with:
|
||||
react-sdk-repository: matrix-org/matrix-react-sdk
|
||||
secrets:
|
||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
# We want to make the Playwright tests a required check for the merge queue.
|
||||
#
|
||||
# Unfortunately, GitHub doesn't distinguish between "checks needed for branch
|
||||
# protection" (ie, the things that must pass before the PR will even be added
|
||||
# to the merge queue) and "checks needed in the merge queue". We just have to add
|
||||
# the check to the branch protection list.
|
||||
#
|
||||
# Ergo, if we know we're not going to run the Playwright tests, we need to add a
|
||||
# passing status check manually.
|
||||
mark_skipped:
|
||||
if: github.event.workflow_run.event != 'merge_group'
|
||||
permissions:
|
||||
statuses: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: Sibz/github-status-action@071b5370da85afbb16637d6eed8524a06bc2053e # v1
|
||||
with:
|
||||
authToken: "${{ secrets.GITHUB_TOKEN }}"
|
||||
state: success
|
||||
description: Playwright skipped
|
||||
|
||||
# Keep in step with the `context` that is updated by `Sibz/github-status-action`
|
||||
# in matrix-org/matrix-react-sdk/.github/workflows/end-to-end-tests.yaml.
|
||||
context: "${{ github.workflow }} / end-to-end-tests"
|
||||
|
||||
sha: "${{ github.event.workflow_run.head_sha }}"
|
||||
# We only want to run the playwright tests on merge queue to prevent regressions
|
||||
# from creeping in. They take a long time to run and consume multiple concurrent runners.
|
||||
skip: ${{ github.event_name != 'merge_group' }}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
name: Release Drafter
|
||||
# Workflow used by other workflows to generate draft releases.
|
||||
name: Release Drafter Reusable
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# Generates the draft release for the js-sdk
|
||||
# Normally triggered whenever anything is merged to the staging branch, but
|
||||
# also has a workflow dispatch trigger in case it needs running manually due
|
||||
# to failures / workflow updates etc.
|
||||
name: Release Drafter
|
||||
on:
|
||||
push:
|
||||
|
||||
@@ -12,10 +12,6 @@ on:
|
||||
type: boolean
|
||||
required: false
|
||||
description: "Whether to combine multiple LCOV and jest-sonar-report files in coverage artifact"
|
||||
extra_args:
|
||||
type: string
|
||||
required: false
|
||||
description: "Extra args to pass to SonarCloud"
|
||||
jobs:
|
||||
sonarqube:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -60,14 +56,14 @@ jobs:
|
||||
|
||||
- id: extra_args
|
||||
run: |
|
||||
coverage=$(find coverage -type f -name '*lcov.info' | tr '\n' ',' | sed 's/,$//g')
|
||||
echo "reportPaths=$coverage" >> $GITHUB_OUTPUT
|
||||
reports=$(find coverage -type f -name 'jest-sonar-report*.xml' | tr '\n' ',' | sed 's/,$//g')
|
||||
echo "testExecutionReportPaths=$reports" >> $GITHUB_OUTPUT
|
||||
coverage=$(find coverage -type f -name '*lcov.info' -printf '%h/%f,' | tr -d '\r\n' | sed 's/,$//g')
|
||||
echo "sonar.javascript.lcov.reportPaths=$coverage" >> sonar-project.properties
|
||||
reports=$(find coverage -type f -name 'jest-sonar-report*.xml' -printf '%h/%f,' | tr -d '\r\n' | sed 's/,$//g')
|
||||
echo "sonar.testExecutionReportPaths=$reports" >> sonar-project.properties
|
||||
|
||||
- name: "🩻 SonarCloud Scan"
|
||||
id: sonarcloud
|
||||
uses: matrix-org/sonarcloud-workflow-action@v2.7
|
||||
uses: matrix-org/sonarcloud-workflow-action@v3.2
|
||||
# workflow_run fails report against the develop commit always, we don't want that for PRs
|
||||
continue-on-error: ${{ github.event.workflow_run.head_branch != 'develop' }}
|
||||
with:
|
||||
@@ -78,10 +74,6 @@ jobs:
|
||||
branch: ${{ github.event.workflow_run.head_branch }}
|
||||
revision: ${{ github.event.workflow_run.head_sha }}
|
||||
token: ${{ secrets.SONAR_TOKEN }}
|
||||
extra_args: |
|
||||
${{ inputs.extra_args }}
|
||||
-Dsonar.javascript.lcov.reportPaths=${{ steps.extra_args.outputs.reportPaths }}
|
||||
-Dsonar.testExecutionReportPaths=${{ steps.extra_args.outputs.testExecutionReportPaths }}
|
||||
|
||||
- uses: Sibz/github-status-action@071b5370da85afbb16637d6eed8524a06bc2053e # v1
|
||||
if: always()
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
Changes in [32.2.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v32.2.0) (2024-05-07)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Use a different error code for UTDs when user was not in the room ([#4172](https://github.com/matrix-org/matrix-js-sdk/pull/4172)). Contributed by @uhoreg.
|
||||
* Modernize window.crypto access constants ([#4169](https://github.com/matrix-org/matrix-js-sdk/pull/4169)). Contributed by @turt2live.
|
||||
* Improve compliance with MSC3266 ([#4155](https://github.com/matrix-org/matrix-js-sdk/pull/4155)). Contributed by @AndrewFerr.
|
||||
* Add comment to make clear that RoomStateEvent.Events does not update related objects in the js-sdk ([#4152](https://github.com/matrix-org/matrix-js-sdk/pull/4152)). Contributed by @toger5.
|
||||
* Crypto: use a new error code for UTDs from device-relative historical events ([#4139](https://github.com/matrix-org/matrix-js-sdk/pull/4139)). Contributed by @richvdh.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Element-R: Fix rust migration when ssss secret are stored not encryted in cache (old legacy behavior) ([#4168](https://github.com/matrix-org/matrix-js-sdk/pull/4168)). Contributed by @BillCarsonFr.
|
||||
|
||||
|
||||
Changes in [32.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v32.1.0) (2024-04-23)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Add support for device dehydration v2 (Element R) ([#4062](https://github.com/matrix-org/matrix-js-sdk/pull/4062)). Contributed by @uhoreg.
|
||||
* OIDC improvements in prep of OIDC-QR reciprocation ([#4149](https://github.com/matrix-org/matrix-js-sdk/pull/4149)). Contributed by @t3chguy.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Validate backup private key before migrating it ([#4114](https://github.com/matrix-org/matrix-js-sdk/pull/4114)). Contributed by @BillCarsonFr.
|
||||
* ElementR| Retry query backup until it works during migration to avoid spurious correption error popup ([#4113](https://github.com/matrix-org/matrix-js-sdk/pull/4113)). Contributed by @BillCarsonFr.
|
||||
|
||||
|
||||
Changes in [32.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v32.0.0) (2024-04-09)
|
||||
==================================================================================================
|
||||
## 🚨 BREAKING CHANGES
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "matrix-js-sdk",
|
||||
"version": "32.1.0-rc.0",
|
||||
"version": "32.2.0",
|
||||
"description": "Matrix Client-Server SDK for Javascript",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -102,11 +102,11 @@
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-jest": "^27.1.6",
|
||||
"eslint-plugin-jest": "^28.0.0",
|
||||
"eslint-plugin-jsdoc": "^48.0.0",
|
||||
"eslint-plugin-matrix-org": "^1.0.0",
|
||||
"eslint-plugin-tsdoc": "^0.2.17",
|
||||
"eslint-plugin-unicorn": "^51.0.0",
|
||||
"eslint-plugin-unicorn": "^52.0.0",
|
||||
"fake-indexeddb": "^5.0.2",
|
||||
"fetch-mock": "9.11.0",
|
||||
"fetch-mock-jest": "^1.5.1",
|
||||
@@ -115,7 +115,7 @@
|
||||
"jest-environment-jsdom": "^29.0.0",
|
||||
"jest-localstorage-mock": "^2.4.6",
|
||||
"jest-mock": "^29.0.0",
|
||||
"knip": "^4.0.1",
|
||||
"knip": "^5.0.0",
|
||||
"lint-staged": "^15.0.2",
|
||||
"matrix-mock-request": "^2.5.0",
|
||||
"node-fetch": "^2.7.0",
|
||||
|
||||
@@ -347,6 +347,67 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("cross-signing (%s)", (backend: s
|
||||
|
||||
expect(isCrossSigningReady).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should return false if identity is not trusted, even if the secrets are in 4S", async () => {
|
||||
e2eKeyResponder.addCrossSigningData(SIGNED_CROSS_SIGNING_KEYS_DATA);
|
||||
|
||||
// Complete initial sync, to get the 4S account_data events stored
|
||||
mockInitialApiRequests(aliceClient.getHomeserverUrl());
|
||||
|
||||
// For this test we need to have a well-formed 4S setup.
|
||||
const mockSecretInfo = {
|
||||
encrypted: {
|
||||
// Don't care about the actual values here, just need to be present for validation
|
||||
KeyId: {
|
||||
iv: "IVIVIVIVIVIVIV",
|
||||
ciphertext: "CIPHERTEXTB64",
|
||||
mac: "MACMACMAC",
|
||||
},
|
||||
},
|
||||
};
|
||||
syncResponder.sendOrQueueSyncResponse({
|
||||
next_batch: 1,
|
||||
account_data: {
|
||||
events: [
|
||||
{
|
||||
type: "m.secret_storage.key.KeyId",
|
||||
content: {
|
||||
algorithm: "m.secret_storage.v1.aes-hmac-sha2",
|
||||
// iv and mac not relevant for this test
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "m.secret_storage.default_key",
|
||||
content: {
|
||||
key: "KeyId",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "m.cross_signing.master",
|
||||
content: mockSecretInfo,
|
||||
},
|
||||
{
|
||||
type: "m.cross_signing.user_signing",
|
||||
content: mockSecretInfo,
|
||||
},
|
||||
{
|
||||
type: "m.cross_signing.self_signing",
|
||||
content: mockSecretInfo,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await aliceClient.startClient();
|
||||
await syncPromise(aliceClient);
|
||||
|
||||
// Sanity: ensure that the secrets are in 4S
|
||||
const status = await aliceClient.getCrypto()!.getCrossSigningStatus();
|
||||
expect(status.privateKeysInSecretStorage).toBeTruthy();
|
||||
|
||||
const isCrossSigningReady = await aliceClient.getCrypto()!.isCrossSigningReady();
|
||||
|
||||
expect(isCrossSigningReady).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getCrossSigningKeyId", () => {
|
||||
|
||||
@@ -101,6 +101,7 @@ import {
|
||||
} from "./olm-utils";
|
||||
import { ToDevicePayload } from "../../../src/models/ToDeviceMessage";
|
||||
import { AccountDataAccumulator } from "../../test-utils/AccountDataAccumulator";
|
||||
import { UNSIGNED_MEMBERSHIP_FIELD } from "../../../src/@types/event";
|
||||
import { KnownMembership } from "../../../src/@types/membership";
|
||||
|
||||
afterEach(() => {
|
||||
@@ -108,6 +109,8 @@ afterEach(() => {
|
||||
// cf https://github.com/dumbmatter/fakeIndexedDB#wipingresetting-the-indexeddb-for-a-fresh-state
|
||||
// eslint-disable-next-line no-global-assign
|
||||
indexedDB = new IDBFactory();
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -467,6 +470,10 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
});
|
||||
|
||||
describe("Unable to decrypt error codes", function () {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers({ doNotFake: ["queueMicrotask"] });
|
||||
});
|
||||
|
||||
it("Decryption fails with UISI error", async () => {
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
@@ -474,11 +481,17 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
// A promise which resolves, with the MatrixEvent which wraps the event, once the decryption fails.
|
||||
const awaitDecryption = emitPromise(aliceClient, MatrixEventEvent.Decrypted);
|
||||
|
||||
// Ensure that the timestamp post-dates the creation of our device
|
||||
const encryptedEvent = {
|
||||
...testData.ENCRYPTED_EVENT,
|
||||
origin_server_ts: Date.now(),
|
||||
};
|
||||
|
||||
const syncResponse = {
|
||||
next_batch: 1,
|
||||
rooms: {
|
||||
join: {
|
||||
[testData.TEST_ROOM_ID]: { timeline: { events: [testData.ENCRYPTED_EVENT] } },
|
||||
[testData.TEST_ROOM_ID]: { timeline: { events: [encryptedEvent] } },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -498,12 +511,17 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
|
||||
await aliceClient.getCrypto()!.importRoomKeys([testData.RATCHTED_MEGOLM_SESSION_DATA]);
|
||||
|
||||
// Alice gets both the events in a single sync
|
||||
// Ensure that the timestamp post-dates the creation of our device
|
||||
const encryptedEvent = {
|
||||
...testData.ENCRYPTED_EVENT,
|
||||
origin_server_ts: Date.now(),
|
||||
};
|
||||
|
||||
const syncResponse = {
|
||||
next_batch: 1,
|
||||
rooms: {
|
||||
join: {
|
||||
[testData.TEST_ROOM_ID]: { timeline: { events: [testData.ENCRYPTED_EVENT] } },
|
||||
[testData.TEST_ROOM_ID]: { timeline: { events: [encryptedEvent] } },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -515,6 +533,151 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
expect(ev.decryptionFailureReason).toEqual(DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX);
|
||||
});
|
||||
|
||||
describe("Historical events", () => {
|
||||
async function sendEventAndAwaitDecryption(props: Partial<IEvent> = {}): Promise<MatrixEvent> {
|
||||
// A promise which resolves, with the MatrixEvent which wraps the event, once the decryption fails.
|
||||
const awaitDecryption = emitPromise(aliceClient, MatrixEventEvent.Decrypted);
|
||||
|
||||
// Ensure that the timestamp pre-dates the creation of our device: set it to 24 hours ago
|
||||
const encryptedEvent = {
|
||||
...testData.ENCRYPTED_EVENT,
|
||||
origin_server_ts: Date.now() - 24 * 3600 * 1000,
|
||||
...props,
|
||||
};
|
||||
|
||||
const syncResponse = {
|
||||
next_batch: 1,
|
||||
rooms: {
|
||||
join: {
|
||||
[testData.TEST_ROOM_ID]: { timeline: { events: [encryptedEvent] } },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
syncResponder.sendOrQueueSyncResponse(syncResponse);
|
||||
return await awaitDecryption;
|
||||
}
|
||||
|
||||
newBackendOnly("fails with HISTORICAL_MESSAGE_BACKUP_NO_BACKUP when there is no backup", async () => {
|
||||
fetchMock.get("path:/_matrix/client/v3/room_keys/version", {
|
||||
status: 404,
|
||||
body: { errcode: "M_NOT_FOUND", error: "No current backup version." },
|
||||
});
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
const ev = await sendEventAndAwaitDecryption();
|
||||
expect(ev.decryptionFailureReason).toEqual(DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP);
|
||||
});
|
||||
|
||||
newBackendOnly("fails with HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED when the backup is broken", async () => {
|
||||
fetchMock.get("path:/_matrix/client/v3/room_keys/version", {});
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
const ev = await sendEventAndAwaitDecryption();
|
||||
expect(ev.decryptionFailureReason).toEqual(
|
||||
DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED,
|
||||
);
|
||||
});
|
||||
|
||||
newBackendOnly("fails with HISTORICAL_MESSAGE_WORKING_BACKUP when backup is working", async () => {
|
||||
// The test backup data is signed by a dummy device. We'll need to tell Alice about the device, and
|
||||
// later, tell her to trust it, so that she trusts the backup.
|
||||
const e2eResponder = new E2EKeyResponder(aliceClient.getHomeserverUrl());
|
||||
e2eResponder.addDeviceKeys(testData.SIGNED_TEST_DEVICE_DATA);
|
||||
fetchMock.get("path:/_matrix/client/v3/room_keys/version", testData.SIGNED_BACKUP_DATA);
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
await aliceClient
|
||||
.getCrypto()!
|
||||
.storeSessionBackupPrivateKey(
|
||||
Buffer.from(testData.BACKUP_DECRYPTION_KEY_BASE64, "base64"),
|
||||
testData.SIGNED_BACKUP_DATA.version!,
|
||||
);
|
||||
|
||||
// Tell Alice to trust the dummy device that signed the backup
|
||||
const devices = await aliceClient.getCrypto()!.getUserDeviceInfo([TEST_USER_ID]);
|
||||
expect(devices.get(TEST_USER_ID)!.keys()).toContain(testData.TEST_DEVICE_ID);
|
||||
await aliceClient.getCrypto()!.setDeviceVerified(testData.TEST_USER_ID, testData.TEST_DEVICE_ID);
|
||||
|
||||
// Tell Alice to check and enable backup
|
||||
await aliceClient.getCrypto()!.checkKeyBackupAndEnable();
|
||||
|
||||
// Sanity: Alice should now have working backup.
|
||||
expect(await aliceClient.getCrypto()!.getActiveSessionBackupVersion()).toEqual(
|
||||
testData.SIGNED_BACKUP_DATA.version,
|
||||
);
|
||||
|
||||
// Finally! we can check what happens when we get an event.
|
||||
const ev = await sendEventAndAwaitDecryption();
|
||||
expect(ev.decryptionFailureReason).toEqual(DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP);
|
||||
});
|
||||
|
||||
newBackendOnly("fails with NOT_JOINED if user is not member of room", async () => {
|
||||
fetchMock.get("path:/_matrix/client/v3/room_keys/version", {
|
||||
status: 404,
|
||||
body: { errcode: "M_NOT_FOUND", error: "No current backup version." },
|
||||
});
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
const ev = await sendEventAndAwaitDecryption({
|
||||
unsigned: {
|
||||
[UNSIGNED_MEMBERSHIP_FIELD.name]: "leave",
|
||||
},
|
||||
});
|
||||
expect(ev.decryptionFailureReason).toEqual(DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED);
|
||||
});
|
||||
|
||||
newBackendOnly(
|
||||
"fails with another error when the server reports user was a member of the room",
|
||||
async () => {
|
||||
// This tests that when the server reports that the user
|
||||
// was invited at the time the event was sent, then we
|
||||
// don't get a HISTORICAL_MESSAGE_USER_NOT_JOINED error,
|
||||
// and instead get some other error, since the user should
|
||||
// have gotten the key for the event.
|
||||
fetchMock.get("path:/_matrix/client/v3/room_keys/version", {
|
||||
status: 404,
|
||||
body: { errcode: "M_NOT_FOUND", error: "No current backup version." },
|
||||
});
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
const ev = await sendEventAndAwaitDecryption({
|
||||
unsigned: {
|
||||
[UNSIGNED_MEMBERSHIP_FIELD.name]: "invite",
|
||||
},
|
||||
});
|
||||
expect(ev.decryptionFailureReason).toEqual(DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP);
|
||||
},
|
||||
);
|
||||
|
||||
newBackendOnly(
|
||||
"fails with another error when the server reports user was a member of the room",
|
||||
async () => {
|
||||
// This tests that when the server reports the user's
|
||||
// membership, and reports that the user was joined, then we
|
||||
// don't get a HISTORICAL_MESSAGE_USER_NOT_JOINED error, and
|
||||
// instead get some other error.
|
||||
fetchMock.get("path:/_matrix/client/v3/room_keys/version", {
|
||||
status: 404,
|
||||
body: { errcode: "M_NOT_FOUND", error: "No current backup version." },
|
||||
});
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
const ev = await sendEventAndAwaitDecryption({
|
||||
unsigned: {
|
||||
[UNSIGNED_MEMBERSHIP_FIELD.name]: "join",
|
||||
},
|
||||
});
|
||||
expect(ev.decryptionFailureReason).toEqual(DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("Decryption fails with Unable to decrypt for other errors", async () => {
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
@@ -997,10 +1160,6 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
return encryptedMessage;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
newBackendOnly("should rotate the session after 2 messages", async () => {
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
@@ -2184,10 +2343,6 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
jest.useFakeTimers({ doNotFake: ["queueMicrotask"] });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
function awaitKeyUploadRequest(): Promise<{ keysCount: number; fallbackKeysCount: number }> {
|
||||
return new Promise((resolve) => {
|
||||
const listener = (url: string, options: RequestInit) => {
|
||||
@@ -2250,10 +2405,6 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
});
|
||||
|
||||
describe("getUserDeviceInfo", () => {
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
// From https://spec.matrix.org/v1.6/client-server-api/#post_matrixclientv3keysquery
|
||||
// Using extracted response from matrix.org, it needs to have real keys etc to pass old crypto verification
|
||||
const queryResponseBody = {
|
||||
@@ -2742,10 +2893,6 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
jest.useFakeTimers({ doNotFake: ["queueMicrotask"] });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("Should be able to restore from 4S after bootstrap", async () => {
|
||||
const backupVersion = "1";
|
||||
await bootstrapSecurity(backupVersion);
|
||||
|
||||
@@ -45,6 +45,7 @@ import { KeyBackupInfo, KeyBackupSession } from "../../../src/crypto-api/keyback
|
||||
import { IKeyBackup } from "../../../src/crypto/backup";
|
||||
import { flushPromises } from "../../test-utils/flushPromises";
|
||||
import { defer, IDeferred } from "../../../src/utils";
|
||||
import { DecryptionFailureCode } from "../../../src/crypto-api";
|
||||
|
||||
const ROOM_ID = testData.TEST_ROOM_ID;
|
||||
|
||||
@@ -242,8 +243,17 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe
|
||||
|
||||
const room = aliceClient.getRoom(ROOM_ID)!;
|
||||
const event = room.getLiveTimeline().getEvents()[0];
|
||||
await advanceTimersUntil(awaitDecryption(event, { waitOnDecryptionFailure: true }));
|
||||
|
||||
// On the first decryption attempt, decryption fails.
|
||||
await awaitDecryption(event);
|
||||
expect(event.decryptionFailureReason).toEqual(
|
||||
backend === "libolm"
|
||||
? DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID
|
||||
: DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP,
|
||||
);
|
||||
|
||||
// Eventually, decryption succeeds.
|
||||
await awaitDecryption(event, { waitOnDecryptionFailure: true });
|
||||
expect(event.getContent()).toEqual(testData.CLEAR_EVENT.content);
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,16 @@ import { Mocked } from "jest-mock";
|
||||
import * as utils from "../test-utils/test-utils";
|
||||
import { CRYPTO_ENABLED, IStoredClientOpts, MatrixClient } from "../../src/client";
|
||||
import { MatrixEvent } from "../../src/models/event";
|
||||
import { Filter, KnockRoomOpts, MemoryStore, Method, Room, SERVICE_TYPES } from "../../src/matrix";
|
||||
import {
|
||||
Filter,
|
||||
JoinRule,
|
||||
KnockRoomOpts,
|
||||
MemoryStore,
|
||||
Method,
|
||||
Room,
|
||||
RoomSummary,
|
||||
SERVICE_TYPES,
|
||||
} from "../../src/matrix";
|
||||
import { TestClient } from "../TestClient";
|
||||
import { THREAD_RELATION_TYPE } from "../../src/models/thread";
|
||||
import { IFilterDefinition } from "../../src/filter";
|
||||
@@ -1710,6 +1719,102 @@ describe("MatrixClient", function () {
|
||||
await Promise.all([client.unbindThreePid("email", "alice@server.com"), httpBackend.flushAllExpected()]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getRoomSummary", () => {
|
||||
const roomId = "!foo:bar";
|
||||
const encodedRoomId = encodeURIComponent(roomId);
|
||||
|
||||
const roomSummary: RoomSummary = {
|
||||
"room_id": roomId,
|
||||
"name": "My Room",
|
||||
"avatar_url": "",
|
||||
"topic": "My room topic",
|
||||
"world_readable": false,
|
||||
"guest_can_join": false,
|
||||
"num_joined_members": 1,
|
||||
"room_type": "",
|
||||
"join_rule": JoinRule.Public,
|
||||
"membership": "leave",
|
||||
"im.nheko.summary.room_version": "6",
|
||||
"im.nheko.summary.encryption": "algo",
|
||||
};
|
||||
|
||||
const prefix = "/_matrix/client/unstable/im.nheko.summary/";
|
||||
const suffix = `summary/${encodedRoomId}`;
|
||||
const deprecatedSuffix = `rooms/${encodedRoomId}/summary`;
|
||||
|
||||
const errorUnrecogStatus = 404;
|
||||
const errorUnrecogBody = {
|
||||
errcode: "M_UNRECOGNIZED",
|
||||
error: "Unsupported endpoint",
|
||||
};
|
||||
|
||||
const errorBadreqStatus = 400;
|
||||
const errorBadreqBody = {
|
||||
errcode: "M_UNKNOWN",
|
||||
error: "Invalid request",
|
||||
};
|
||||
|
||||
it("should respond with a valid room summary object", () => {
|
||||
httpBackend.when("GET", prefix + suffix).respond(200, roomSummary);
|
||||
|
||||
const prom = client.getRoomSummary(roomId).then((response) => {
|
||||
expect(response).toEqual(roomSummary);
|
||||
});
|
||||
|
||||
httpBackend.flush("");
|
||||
return prom;
|
||||
});
|
||||
|
||||
it("should allow fallback to the deprecated endpoint", () => {
|
||||
httpBackend.when("GET", prefix + suffix).respond(errorUnrecogStatus, errorUnrecogBody);
|
||||
httpBackend.when("GET", prefix + deprecatedSuffix).respond(200, roomSummary);
|
||||
|
||||
const prom = client.getRoomSummary(roomId).then((response) => {
|
||||
expect(response).toEqual(roomSummary);
|
||||
});
|
||||
|
||||
httpBackend.flush("");
|
||||
return prom;
|
||||
});
|
||||
|
||||
it("should respond to unsupported path with error", () => {
|
||||
httpBackend.when("GET", prefix + suffix).respond(errorUnrecogStatus, errorUnrecogBody);
|
||||
httpBackend.when("GET", prefix + deprecatedSuffix).respond(errorUnrecogStatus, errorUnrecogBody);
|
||||
|
||||
const prom = client.getRoomSummary(roomId).then(
|
||||
function (response) {
|
||||
throw Error("request not failed");
|
||||
},
|
||||
function (error) {
|
||||
expect(error.httpStatus).toEqual(errorUnrecogStatus);
|
||||
expect(error.errcode).toEqual(errorUnrecogBody.errcode);
|
||||
expect(error.message).toEqual(`MatrixError: [${errorUnrecogStatus}] ${errorUnrecogBody.error}`);
|
||||
},
|
||||
);
|
||||
|
||||
httpBackend.flush("");
|
||||
return prom;
|
||||
});
|
||||
|
||||
it("should respond to invalid path arguments with error", () => {
|
||||
httpBackend.when("GET", prefix).respond(errorBadreqStatus, errorBadreqBody);
|
||||
|
||||
const prom = client.getRoomSummary("notAroom").then(
|
||||
function (response) {
|
||||
throw Error("request not failed");
|
||||
},
|
||||
function (error) {
|
||||
expect(error.httpStatus).toEqual(errorBadreqStatus);
|
||||
expect(error.errcode).toEqual(errorBadreqBody.errcode);
|
||||
expect(error.message).toEqual(`MatrixError: [${errorBadreqStatus}] ${errorBadreqBody.error}`);
|
||||
},
|
||||
);
|
||||
|
||||
httpBackend.flush("");
|
||||
return prom;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function withThreadId(event: MatrixEvent, newThreadId: string): MatrixEvent {
|
||||
|
||||
@@ -90,7 +90,7 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
|
||||
mockRustBackupManager = {
|
||||
getActiveBackupVersion: jest.fn(),
|
||||
requestKeyBackupVersion: jest.fn(),
|
||||
getServerBackupInfo: jest.fn(),
|
||||
importBackedUpRoomKeys: jest.fn(),
|
||||
createBackupDecryptor: jest.fn().mockReturnValue(mockBackupDecryptor),
|
||||
on: jest.fn().mockImplementation((event, listener) => {
|
||||
@@ -135,7 +135,7 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
decryptionKey: RustSdkCryptoJs.BackupDecryptionKey.fromBase64(TestData.BACKUP_DECRYPTION_KEY_BASE64),
|
||||
} as unknown as RustSdkCryptoJs.BackupKeys);
|
||||
|
||||
mockRustBackupManager.requestKeyBackupVersion.mockResolvedValue(TestData.SIGNED_BACKUP_DATA);
|
||||
mockRustBackupManager.getServerBackupInfo.mockResolvedValue(TestData.SIGNED_BACKUP_DATA);
|
||||
});
|
||||
|
||||
it("Should download and import a missing key from backup", async () => {
|
||||
@@ -155,8 +155,11 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
|
||||
downloader.onDecryptionKeyMissingError(roomId, sessionId);
|
||||
|
||||
// `isKeyBackupDownloadConfigured` is false until the config is proven.
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(false);
|
||||
await expectAPICall;
|
||||
await awaitKeyImported.promise;
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(true);
|
||||
expect(mockRustBackupManager.createBackupDecryptor).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -313,6 +316,9 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
|
||||
expect(getConfigSpy).toHaveBeenCalledTimes(1);
|
||||
expect(getConfigSpy).toHaveReturnedWith(Promise.resolve(null));
|
||||
|
||||
// isKeyBackupDownloadConfigured remains false
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(false);
|
||||
});
|
||||
|
||||
it("Should not query server if backup not active", async () => {
|
||||
@@ -328,6 +334,9 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
|
||||
expect(getConfigSpy).toHaveBeenCalledTimes(1);
|
||||
expect(getConfigSpy).toHaveReturnedWith(Promise.resolve(null));
|
||||
|
||||
// isKeyBackupDownloadConfigured remains false
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(false);
|
||||
});
|
||||
|
||||
it("Should stop if backup key is not cached", async () => {
|
||||
@@ -344,6 +353,9 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
|
||||
expect(getConfigSpy).toHaveBeenCalledTimes(1);
|
||||
expect(getConfigSpy).toHaveReturnedWith(Promise.resolve(null));
|
||||
|
||||
// isKeyBackupDownloadConfigured remains false
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(false);
|
||||
});
|
||||
|
||||
it("Should stop if backup key cached as wrong version", async () => {
|
||||
@@ -363,6 +375,9 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
|
||||
expect(getConfigSpy).toHaveBeenCalledTimes(1);
|
||||
expect(getConfigSpy).toHaveReturnedWith(Promise.resolve(null));
|
||||
|
||||
// isKeyBackupDownloadConfigured remains false
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(false);
|
||||
});
|
||||
|
||||
it("Should stop if backup key version does not match the active one", async () => {
|
||||
@@ -382,13 +397,16 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
|
||||
expect(getConfigSpy).toHaveBeenCalledTimes(1);
|
||||
expect(getConfigSpy).toHaveReturnedWith(Promise.resolve(null));
|
||||
|
||||
// isKeyBackupDownloadConfigured remains false
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Given Backup state update", () => {
|
||||
it("After initial sync, when backup becomes trusted it should request keys for past requests", async () => {
|
||||
// there is a backup
|
||||
mockRustBackupManager.requestKeyBackupVersion.mockResolvedValue(TestData.SIGNED_BACKUP_DATA);
|
||||
mockRustBackupManager.getServerBackupInfo.mockResolvedValue(TestData.SIGNED_BACKUP_DATA);
|
||||
|
||||
// but at this point it's not trusted and we don't have the key
|
||||
mockRustBackupManager.getActiveBackupVersion.mockResolvedValue(null);
|
||||
@@ -410,6 +428,7 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
|
||||
// @ts-ignore access to private property
|
||||
expect(downloader.hasConfigurationProblem).toEqual(true);
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(false);
|
||||
|
||||
// Now the backup becomes trusted
|
||||
mockRustBackupManager.getActiveBackupVersion.mockResolvedValue(TestData.SIGNED_BACKUP_DATA.version!);
|
||||
@@ -423,6 +442,7 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
mockEmitter.emit(CryptoEvent.KeyBackupStatus, true);
|
||||
|
||||
await jest.runAllTimersAsync();
|
||||
expect(downloader.isKeyBackupDownloadConfigured()).toBe(true);
|
||||
|
||||
await a0Imported;
|
||||
await a1Imported;
|
||||
@@ -434,7 +454,7 @@ describe("PerSessionKeyBackupDownloader", () => {
|
||||
describe("Error cases", () => {
|
||||
beforeEach(async () => {
|
||||
// there is a backup
|
||||
mockRustBackupManager.requestKeyBackupVersion.mockResolvedValue(TestData.SIGNED_BACKUP_DATA);
|
||||
mockRustBackupManager.getServerBackupInfo.mockResolvedValue(TestData.SIGNED_BACKUP_DATA);
|
||||
// It's trusted
|
||||
mockRustBackupManager.getActiveBackupVersion.mockResolvedValue(TestData.SIGNED_BACKUP_DATA.version!);
|
||||
// And we have the key in cache
|
||||
|
||||
@@ -304,6 +304,56 @@ describe("initRustCrypto", () => {
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
it("migrates data from a legacy crypto store when secret are not encrypted", async () => {
|
||||
const PICKLE_KEY = "pickle1234";
|
||||
const legacyStore = new MemoryCryptoStore();
|
||||
|
||||
// It's possible for old sessions to directly store the secrets as raw UInt8Array,
|
||||
// so we need to support that in the migration code.
|
||||
// See https://github.com/matrix-org/matrix-js-sdk/commit/c81f11df0afd4d0da3b088892745ae2f8ba1c4a7
|
||||
async function storeSecretKeyInClear(type: string, key: Uint8Array, store: CryptoStore) {
|
||||
// @ts-ignore The API to store raw UInt8Array does not exist anymore, so we need that for this test.
|
||||
store.privateKeys[type as keyof SecretStorePrivateKeys] = key;
|
||||
}
|
||||
|
||||
// Populate the legacy store with some test data
|
||||
const storeSecretKey = (type: string, key: string) =>
|
||||
storeSecretKeyInClear(type, new TextEncoder().encode(key), legacyStore);
|
||||
|
||||
await legacyStore.storeAccount({}, "not a real account");
|
||||
await storeSecretKey("master", "master key");
|
||||
await storeSecretKey("self_signing", "ssk");
|
||||
await storeSecretKey("user_signing", "usk");
|
||||
|
||||
fetchMock.get("path:/_matrix/client/v3/room_keys/version", 404);
|
||||
|
||||
function legacyMigrationProgressListener(progress: number, total: number): void {
|
||||
logger.log(`migrated ${progress} of ${total}`);
|
||||
}
|
||||
|
||||
await initRustCrypto({
|
||||
logger,
|
||||
http: makeMatrixHttpApi(),
|
||||
userId: TEST_USER,
|
||||
deviceId: TEST_DEVICE_ID,
|
||||
secretStorage: {} as ServerSideSecretStorage,
|
||||
cryptoCallbacks: {} as CryptoCallbacks,
|
||||
storePrefix: "storePrefix",
|
||||
storePassphrase: "storePassphrase",
|
||||
legacyCryptoStore: legacyStore,
|
||||
legacyPickleKey: PICKLE_KEY,
|
||||
legacyMigrationProgressListener,
|
||||
});
|
||||
|
||||
const data = mocked(Migration.migrateBaseData).mock.calls[0][0];
|
||||
expect(data.pickledAccount).toEqual("not a real account");
|
||||
expect(data.userId!.toString()).toEqual(TEST_USER);
|
||||
expect(data.deviceId!.toString()).toEqual(TEST_DEVICE_ID);
|
||||
expect(atob(data.privateCrossSigningMasterKey!)).toEqual("master key");
|
||||
expect(atob(data.privateCrossSigningUserSigningKey!)).toEqual("usk");
|
||||
expect(atob(data.privateCrossSigningSelfSigningKey!)).toEqual("ssk");
|
||||
});
|
||||
|
||||
it("handles megolm sessions with no `keysClaimed`", async () => {
|
||||
const legacyStore = new MemoryCryptoStore();
|
||||
legacyStore.storeAccount({}, "not a real account");
|
||||
|
||||
@@ -298,6 +298,13 @@ export const LOCAL_NOTIFICATION_SETTINGS_PREFIX = new UnstableValue(
|
||||
*/
|
||||
export const UNSIGNED_THREAD_ID_FIELD = new UnstableValue("thread_id", "org.matrix.msc4023.thread_id");
|
||||
|
||||
/**
|
||||
* https://github.com/matrix-org/matrix-spec-proposals/pull/4115
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export const UNSIGNED_MEMBERSHIP_FIELD = new UnstableValue("membership", "io.element.msc4115.membership");
|
||||
|
||||
/**
|
||||
* @deprecated in favour of {@link EncryptedFile}
|
||||
*/
|
||||
|
||||
+32
-8
@@ -865,10 +865,24 @@ interface IThirdPartyUser {
|
||||
fields: object;
|
||||
}
|
||||
|
||||
interface IRoomSummary extends Omit<IPublicRoomsChunkRoom, "canonical_alias" | "aliases"> {
|
||||
room_type?: RoomType;
|
||||
membership?: Membership;
|
||||
is_encrypted: boolean;
|
||||
/**
|
||||
* The summary of a room as defined by an initial version of MSC3266 and implemented in Synapse
|
||||
* Proposed at https://github.com/matrix-org/matrix-doc/pull/3266
|
||||
*/
|
||||
export interface RoomSummary extends Omit<IPublicRoomsChunkRoom, "canonical_alias" | "aliases"> {
|
||||
/**
|
||||
* The current membership of this user in the room.
|
||||
* Usually "leave" if the room is fetched over federation.
|
||||
*/
|
||||
"membership"?: Membership;
|
||||
/**
|
||||
* Version of the room.
|
||||
*/
|
||||
"im.nheko.summary.room_version"?: string;
|
||||
/**
|
||||
* The encryption algorithm used for this room, if the room is encrypted.
|
||||
*/
|
||||
"im.nheko.summary.encryption"?: string;
|
||||
}
|
||||
|
||||
interface IRoomKeysResponse {
|
||||
@@ -9786,11 +9800,21 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
* @param roomIdOrAlias - The ID or alias of the room to get the summary of.
|
||||
* @param via - The list of servers which know about the room if only an ID was provided.
|
||||
*/
|
||||
public async getRoomSummary(roomIdOrAlias: string, via?: string[]): Promise<IRoomSummary> {
|
||||
const path = utils.encodeUri("/rooms/$roomid/summary", { $roomid: roomIdOrAlias });
|
||||
return this.http.authedRequest(Method.Get, path, { via }, undefined, {
|
||||
public async getRoomSummary(roomIdOrAlias: string, via?: string[]): Promise<RoomSummary> {
|
||||
const paramOpts = {
|
||||
prefix: "/_matrix/client/unstable/im.nheko.summary",
|
||||
});
|
||||
};
|
||||
try {
|
||||
const path = utils.encodeUri("/summary/$roomid", { $roomid: roomIdOrAlias });
|
||||
return await this.http.authedRequest(Method.Get, path, { via }, undefined, paramOpts);
|
||||
} catch (e) {
|
||||
if (e instanceof MatrixError && e.errcode === "M_UNRECOGNIZED") {
|
||||
const path = utils.encodeUri("/rooms/$roomid/summary", { $roomid: roomIdOrAlias });
|
||||
return await this.http.authedRequest(Method.Get, path, { via }, undefined, paramOpts);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -542,6 +542,29 @@ export enum DecryptionFailureCode {
|
||||
/** Message was encrypted with a Megolm session which has been shared with us, but in a later ratchet state. */
|
||||
OLM_UNKNOWN_MESSAGE_INDEX = "OLM_UNKNOWN_MESSAGE_INDEX",
|
||||
|
||||
/**
|
||||
* Message was sent before the current device was created; there is no key backup on the server, so this
|
||||
* decryption failure is expected.
|
||||
*/
|
||||
HISTORICAL_MESSAGE_NO_KEY_BACKUP = "HISTORICAL_MESSAGE_NO_KEY_BACKUP",
|
||||
|
||||
/**
|
||||
* Message was sent before the current device was created; there was a key backup on the server, but we don't
|
||||
* seem to have access to the backup. (Probably we don't have the right key.)
|
||||
*/
|
||||
HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED = "HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED",
|
||||
|
||||
/**
|
||||
* Message was sent before the current device was created; there was a (usable) key backup on the server, but we
|
||||
* still can't decrypt. (Either the session isn't in the backup, or we just haven't gotten around to checking yet.)
|
||||
*/
|
||||
HISTORICAL_MESSAGE_WORKING_BACKUP = "HISTORICAL_MESSAGE_WORKING_BACKUP",
|
||||
|
||||
/**
|
||||
* Message was sent when the user was not a member of the room.
|
||||
*/
|
||||
HISTORICAL_MESSAGE_USER_NOT_JOINED = "HISTORICAL_MESSAGE_USER_NOT_JOINED",
|
||||
|
||||
/** Unknown or unclassified error. */
|
||||
UNKNOWN_ERROR = "UNKNOWN_ERROR",
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ limitations under the License.
|
||||
|
||||
import { logger } from "../logger";
|
||||
|
||||
export let crypto = globalThis.window?.crypto;
|
||||
export let subtleCrypto = globalThis.window?.crypto?.subtle ?? global.window?.crypto?.webkitSubtle;
|
||||
export let TextEncoder = globalThis.window?.TextEncoder;
|
||||
export let crypto = globalThis.crypto;
|
||||
export let subtleCrypto = crypto?.subtle ?? crypto?.webkitSubtle; // TODO: Stop using webkitSubtle fallback
|
||||
export let TextEncoder = globalThis.TextEncoder;
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
if (!crypto) {
|
||||
|
||||
@@ -37,6 +37,17 @@ import { IOlmDevice } from "../algorithms/megolm";
|
||||
import { IRoomEncryption } from "../RoomList";
|
||||
import { InboundGroupSessionData } from "../OlmDevice";
|
||||
|
||||
function encodeSessionKey(senderCurve25519Key: string, sessionId: string): string {
|
||||
return encodeURIComponent(senderCurve25519Key) + "/" + encodeURIComponent(sessionId);
|
||||
}
|
||||
|
||||
function decodeSessionKey(key: string): { senderKey: string; sessionId: string } {
|
||||
const keyParts = key.split("/");
|
||||
const senderKey = decodeURIComponent(keyParts[0]);
|
||||
const sessionId = decodeURIComponent(keyParts[1]);
|
||||
return { senderKey, sessionId };
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal module. in-memory storage for e2e.
|
||||
*/
|
||||
@@ -481,20 +492,14 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
txn: unknown,
|
||||
func: (groupSession: InboundGroupSessionData | null, groupSessionWithheld: IWithheld | null) => void,
|
||||
): void {
|
||||
const k = senderCurve25519Key + "/" + sessionId;
|
||||
const k = encodeSessionKey(senderCurve25519Key, sessionId);
|
||||
func(this.inboundGroupSessions[k] || null, this.inboundGroupSessionsWithheld[k] || null);
|
||||
}
|
||||
|
||||
public getAllEndToEndInboundGroupSessions(txn: unknown, func: (session: ISession | null) => void): void {
|
||||
for (const key of Object.keys(this.inboundGroupSessions)) {
|
||||
// we can't use split, as the components we are trying to split out
|
||||
// might themselves contain '/' characters. We rely on the
|
||||
// senderKey being a (32-byte) curve25519 key, base64-encoded
|
||||
// (hence 43 characters long).
|
||||
|
||||
func({
|
||||
senderKey: key.slice(0, 43),
|
||||
sessionId: key.slice(44),
|
||||
...decodeSessionKey(key),
|
||||
sessionData: this.inboundGroupSessions[key],
|
||||
});
|
||||
}
|
||||
@@ -507,7 +512,7 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
sessionData: InboundGroupSessionData,
|
||||
txn: unknown,
|
||||
): void {
|
||||
const k = senderCurve25519Key + "/" + sessionId;
|
||||
const k = encodeSessionKey(senderCurve25519Key, sessionId);
|
||||
if (this.inboundGroupSessions[k] === undefined) {
|
||||
this.inboundGroupSessions[k] = sessionData;
|
||||
}
|
||||
@@ -519,7 +524,8 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
sessionData: InboundGroupSessionData,
|
||||
txn: unknown,
|
||||
): void {
|
||||
this.inboundGroupSessions[senderCurve25519Key + "/" + sessionId] = sessionData;
|
||||
const k = encodeSessionKey(senderCurve25519Key, sessionId);
|
||||
this.inboundGroupSessions[k] = sessionData;
|
||||
}
|
||||
|
||||
public storeEndToEndInboundGroupSessionWithheld(
|
||||
@@ -528,7 +534,7 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
sessionData: IWithheld,
|
||||
txn: unknown,
|
||||
): void {
|
||||
const k = senderCurve25519Key + "/" + sessionId;
|
||||
const k = encodeSessionKey(senderCurve25519Key, sessionId);
|
||||
this.inboundGroupSessionsWithheld[k] = sessionData;
|
||||
}
|
||||
|
||||
@@ -554,8 +560,7 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
const result: SessionExtended[] = [];
|
||||
for (const [key, session] of Object.entries(this.inboundGroupSessions)) {
|
||||
result.push({
|
||||
senderKey: key.slice(0, 43),
|
||||
sessionId: key.slice(44),
|
||||
...decodeSessionKey(key),
|
||||
sessionData: session,
|
||||
needsBackup: key in this.sessionsNeedingBackup,
|
||||
});
|
||||
@@ -584,7 +589,7 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
sessions: { senderKey: string; sessionId: string }[],
|
||||
): Promise<void> {
|
||||
for (const { senderKey, sessionId } of sessions) {
|
||||
const k = senderKey + "/" + sessionId;
|
||||
const k = encodeSessionKey(senderKey, sessionId);
|
||||
delete this.inboundGroupSessions[k];
|
||||
}
|
||||
}
|
||||
@@ -614,8 +619,7 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
for (const session in this.sessionsNeedingBackup) {
|
||||
if (this.inboundGroupSessions[session]) {
|
||||
sessions.push({
|
||||
senderKey: session.slice(0, 43),
|
||||
sessionId: session.slice(44),
|
||||
...decodeSessionKey(session),
|
||||
sessionData: this.inboundGroupSessions[session],
|
||||
});
|
||||
if (limit && session.length >= limit) {
|
||||
@@ -632,7 +636,7 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
|
||||
public unmarkSessionsNeedingBackup(sessions: ISession[]): Promise<void> {
|
||||
for (const session of sessions) {
|
||||
const sessionKey = session.senderKey + "/" + session.sessionId;
|
||||
const sessionKey = encodeSessionKey(session.senderKey, session.sessionId);
|
||||
delete this.sessionsNeedingBackup[sessionKey];
|
||||
}
|
||||
return Promise.resolve();
|
||||
@@ -640,7 +644,7 @@ export class MemoryCryptoStore implements CryptoStore {
|
||||
|
||||
public markSessionsNeedingBackup(sessions: ISession[]): Promise<void> {
|
||||
for (const session of sessions) {
|
||||
const sessionKey = session.senderKey + "/" + session.sessionId;
|
||||
const sessionKey = encodeSessionKey(session.senderKey, session.sessionId);
|
||||
this.sessionsNeedingBackup[sessionKey] = true;
|
||||
}
|
||||
return Promise.resolve();
|
||||
|
||||
@@ -77,6 +77,7 @@ export * from "./@types/extensible_events";
|
||||
export * from "./@types/IIdentityServerProvider";
|
||||
export * from "./models/room-summary";
|
||||
export * from "./models/event-status";
|
||||
export type { RoomSummary } from "./client";
|
||||
export * as ContentHelpers from "./content-helpers";
|
||||
export * as SecretStorage from "./secret-storage";
|
||||
export type { ICryptoCallbacks } from "./crypto"; // used to be located here
|
||||
|
||||
@@ -136,7 +136,6 @@ export class MatrixRTCSession extends TypedEventEmitter<MatrixRTCSessionEvent, M
|
||||
for (const memberEvent of callMemberEvents) {
|
||||
const eventMemberships: CallMembershipData[] = memberEvent.getContent()["memberships"];
|
||||
if (eventMemberships === undefined) {
|
||||
logger.debug(`Ignoring malformed member event from ${memberEvent.getSender()}: no memberships section`);
|
||||
continue;
|
||||
}
|
||||
if (!Array.isArray(eventMemberships)) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
RelationType,
|
||||
ToDeviceMessageId,
|
||||
UNSIGNED_THREAD_ID_FIELD,
|
||||
UNSIGNED_MEMBERSHIP_FIELD,
|
||||
} from "../@types/event";
|
||||
import { Crypto } from "../crypto";
|
||||
import { deepSortedObjectEntries, internaliseString } from "../utils";
|
||||
@@ -76,6 +77,7 @@ export interface IUnsigned {
|
||||
"invite_room_state"?: StrippedState[];
|
||||
"m.relations"?: Record<RelationType | string, any>; // No common pattern for aggregated relations
|
||||
[UNSIGNED_THREAD_ID_FIELD.name]?: string;
|
||||
[UNSIGNED_MEMBERSHIP_FIELD.name]?: Membership | string;
|
||||
}
|
||||
|
||||
export interface IThreadBundledRelationship {
|
||||
@@ -721,6 +723,22 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
||||
return this.event.state_key !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's room membership at the time the event was sent, as reported
|
||||
* by the server. This uses MSC4115.
|
||||
*
|
||||
* @returns The user's room membership, or `undefined` if the server does
|
||||
* not report it.
|
||||
*/
|
||||
public getMembershipAtEvent(): Membership | string | undefined {
|
||||
const unsigned = this.getUnsigned();
|
||||
if (typeof unsigned[UNSIGNED_MEMBERSHIP_FIELD.name] === "string") {
|
||||
return unsigned[UNSIGNED_MEMBERSHIP_FIELD.name];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the content of this event with encrypted versions.
|
||||
* (This is used when sending an event; it should not be used by applications).
|
||||
|
||||
@@ -78,6 +78,8 @@ export enum RoomStateEvent {
|
||||
export type RoomStateEventHandlerMap = {
|
||||
/**
|
||||
* Fires whenever the event dictionary in room state is updated.
|
||||
* This does not guarantee that any related objects (like RoomMember) have been updated.
|
||||
* Use RoomStateEvent.Update for that.
|
||||
* @param event - The matrix event which caused this event to fire.
|
||||
* @param state - The room state whose RoomState.events dictionary
|
||||
* was updated.
|
||||
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-wasm";
|
||||
import { OlmMachine } from "@matrix-org/matrix-sdk-crypto-wasm";
|
||||
|
||||
import { Curve25519AuthData, KeyBackupSession } from "../crypto-api/keybackup";
|
||||
import { Curve25519AuthData, KeyBackupInfo, KeyBackupSession } from "../crypto-api/keybackup";
|
||||
import { Logger } from "../logger";
|
||||
import { ClientPrefix, IHttpOpts, MatrixError, MatrixHttpApi, Method } from "../http-api";
|
||||
import { RustBackupManager } from "./backup";
|
||||
@@ -76,7 +76,11 @@ type Configuration = {
|
||||
export class PerSessionKeyBackupDownloader {
|
||||
private stopped = false;
|
||||
|
||||
/** The version and decryption key to use with current backup if all set up correctly */
|
||||
/**
|
||||
* The version and decryption key to use with current backup if all set up correctly.
|
||||
*
|
||||
* Will not be set unless `hasConfigurationProblem` is `false`.
|
||||
*/
|
||||
private configuration: Configuration | null = null;
|
||||
|
||||
/** We remember when a session was requested and not found in backup to avoid query again too soon.
|
||||
@@ -119,6 +123,24 @@ export class PerSessionKeyBackupDownloader {
|
||||
backupManager.on(CryptoEvent.KeyBackupDecryptionKeyCached, this.onBackupStatusChanged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if key download is successfully configured and active.
|
||||
*
|
||||
* @return `true` if key download is correctly configured and active; otherwise `false`.
|
||||
*/
|
||||
public isKeyBackupDownloadConfigured(): boolean {
|
||||
return this.configuration !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the details of the latest backup on the server, when we last checked.
|
||||
*
|
||||
* This is just a convenience method to expose {@link RustBackupManager.getServerBackupInfo}.
|
||||
*/
|
||||
public async getServerBackupInfo(): Promise<KeyBackupInfo | null | undefined> {
|
||||
return await this.backupManager.getServerBackupInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a MissingRoomKey or UnknownMessageIndex decryption error is encountered.
|
||||
*
|
||||
@@ -410,7 +432,7 @@ export class PerSessionKeyBackupDownloader {
|
||||
private async internalCheckFromServer(): Promise<Configuration | null> {
|
||||
let currentServerVersion = null;
|
||||
try {
|
||||
currentServerVersion = await this.backupManager.requestKeyBackupVersion();
|
||||
currentServerVersion = await this.backupManager.getServerBackupInfo();
|
||||
} catch (e) {
|
||||
this.logger.debug(`Backup: error while checking server version: ${e}`);
|
||||
this.hasConfigurationProblem = true;
|
||||
|
||||
@@ -58,6 +58,16 @@ interface KeyBackupCreationInfo {
|
||||
export class RustBackupManager extends TypedEventEmitter<RustBackupCryptoEvents, RustBackupCryptoEventMap> {
|
||||
/** Have we checked if there is a backup on the server which we can use */
|
||||
private checkedForBackup = false;
|
||||
|
||||
/**
|
||||
* The latest backup version on the server, when we last checked.
|
||||
*
|
||||
* If there was no backup on the server, `null`. If our attempt to check resulted in an error, `undefined`.
|
||||
*
|
||||
* Note that the backup was not necessarily verified.
|
||||
*/
|
||||
private serverBackupInfo: KeyBackupInfo | null | undefined = undefined;
|
||||
|
||||
private activeBackupVersion: string | null = null;
|
||||
private stopped = false;
|
||||
|
||||
@@ -89,6 +99,21 @@ export class RustBackupManager extends TypedEventEmitter<RustBackupCryptoEvents,
|
||||
return this.activeBackupVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the details of the latest backup on the server, when we last checked.
|
||||
*
|
||||
* This normally returns a cached value, but if we haven't yet made a request to the server, it will fire one off.
|
||||
* It will always return the details of the active backup if key backup is enabled.
|
||||
*
|
||||
* If there was no backup on the server, `null`. If our attempt to check resulted in an error, `undefined`.
|
||||
*/
|
||||
public async getServerBackupInfo(): Promise<KeyBackupInfo | null | undefined> {
|
||||
// Do a validity check if we haven't already done one. The check is likely to fail if we don't yet have the
|
||||
// backup keys -- but as a side-effect, it will populate `serverBackupInfo`.
|
||||
await this.checkKeyBackupAndEnable(false);
|
||||
return this.serverBackupInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a key backup can be trusted.
|
||||
*
|
||||
@@ -242,18 +267,21 @@ export class RustBackupManager extends TypedEventEmitter<RustBackupCryptoEvents,
|
||||
/** Helper for `checkKeyBackup` */
|
||||
private async doCheckKeyBackup(): Promise<KeyBackupCheck | null> {
|
||||
logger.log("Checking key backup status...");
|
||||
let backupInfo: KeyBackupInfo | null = null;
|
||||
let backupInfo: KeyBackupInfo | null | undefined;
|
||||
try {
|
||||
backupInfo = await this.requestKeyBackupVersion();
|
||||
} catch (e) {
|
||||
logger.warn("Error checking for active key backup", e);
|
||||
this.serverBackupInfo = undefined;
|
||||
return null;
|
||||
}
|
||||
this.checkedForBackup = true;
|
||||
|
||||
if (backupInfo && !backupInfo.version) {
|
||||
logger.warn("active backup lacks a useful 'version'; ignoring it");
|
||||
backupInfo = undefined;
|
||||
}
|
||||
this.serverBackupInfo = backupInfo;
|
||||
|
||||
const activeVersion = await this.getActiveBackupVersion();
|
||||
|
||||
@@ -462,12 +490,13 @@ export class RustBackupManager extends TypedEventEmitter<RustBackupCryptoEvents,
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about the current key backup from the server
|
||||
*
|
||||
* @returns Information object from API or null if there is no active backup.
|
||||
*/
|
||||
public async requestKeyBackupVersion(): Promise<KeyBackupInfo | null> {
|
||||
private async requestKeyBackupVersion(): Promise<KeyBackupInfo | null> {
|
||||
return await requestKeyBackupVersion(this.http);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import { CrossSigningKeyInfo, Curve25519AuthData } from "../crypto-api";
|
||||
import { RustCrypto } from "./rust-crypto";
|
||||
import { KeyBackupInfo } from "../crypto-api/keybackup";
|
||||
import { sleep } from "../utils";
|
||||
import { encodeBase64 } from "../base64";
|
||||
|
||||
/**
|
||||
* Determine if any data needs migrating from the legacy store, and do so.
|
||||
@@ -400,19 +401,20 @@ async function getAndDecryptCachedSecretKey(
|
||||
legacyPickleKey: Uint8Array,
|
||||
name: string,
|
||||
): Promise<string | undefined> {
|
||||
let encodedKey: IEncryptedPayload | null = null;
|
||||
|
||||
await legacyStore.doTxn("readonly", "account", (txn) => {
|
||||
legacyStore.getSecretStorePrivateKey(
|
||||
txn,
|
||||
(k) => {
|
||||
encodedKey = k as IEncryptedPayload | null;
|
||||
},
|
||||
name as keyof SecretStorePrivateKeys,
|
||||
);
|
||||
const key = await new Promise<any>((resolve) => {
|
||||
legacyStore.doTxn("readonly", [IndexedDBCryptoStore.STORE_ACCOUNT], (txn) => {
|
||||
legacyStore.getSecretStorePrivateKey(txn, resolve, name as keyof SecretStorePrivateKeys);
|
||||
});
|
||||
});
|
||||
|
||||
return encodedKey === null ? undefined : await decryptAES(encodedKey, legacyPickleKey, name);
|
||||
if (key && key.ciphertext && key.iv && key.mac) {
|
||||
return await decryptAES(key as IEncryptedPayload, legacyPickleKey, name);
|
||||
} else if (key instanceof Uint8Array) {
|
||||
// This is a legacy backward compatibility case where the key was stored in clear.
|
||||
return encodeBase64(key);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@ import anotherjson from "another-json";
|
||||
import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-wasm";
|
||||
|
||||
import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto";
|
||||
import { KnownMembership } from "../@types/membership";
|
||||
import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
|
||||
import type { IEncryptedEventInfo } from "../crypto/api";
|
||||
import { IContent, MatrixEvent, MatrixEventEvent } from "../models/event";
|
||||
@@ -610,15 +611,17 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
* Implementation of {@link CryptoApi#isCrossSigningReady}
|
||||
*/
|
||||
public async isCrossSigningReady(): Promise<boolean> {
|
||||
const { publicKeysOnDevice, privateKeysInSecretStorage, privateKeysCachedLocally } =
|
||||
await this.getCrossSigningStatus();
|
||||
const { privateKeysInSecretStorage, privateKeysCachedLocally } = await this.getCrossSigningStatus();
|
||||
const hasKeysInCache =
|
||||
Boolean(privateKeysCachedLocally.masterKey) &&
|
||||
Boolean(privateKeysCachedLocally.selfSigningKey) &&
|
||||
Boolean(privateKeysCachedLocally.userSigningKey);
|
||||
|
||||
// The cross signing is ready if the public and private keys are available
|
||||
return publicKeysOnDevice && (hasKeysInCache || privateKeysInSecretStorage);
|
||||
const identity = await this.getOwnIdentity();
|
||||
|
||||
// Cross-signing is ready if the public identity is trusted, and the private keys
|
||||
// are either cached, or accessible via secret-storage.
|
||||
return !!identity?.isVerified() && (hasKeysInCache || privateKeysInSecretStorage);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1707,7 +1710,7 @@ class EventDecryptor {
|
||||
};
|
||||
} catch (err) {
|
||||
if (err instanceof RustSdkCryptoJs.MegolmDecryptionError) {
|
||||
this.onMegolmDecryptionError(event, err);
|
||||
this.onMegolmDecryptionError(event, err, await this.perSessionBackupDownloader.getServerBackupInfo());
|
||||
} else {
|
||||
throw new DecryptionError(DecryptionFailureCode.UNKNOWN_ERROR, "Unknown error");
|
||||
}
|
||||
@@ -1718,9 +1721,19 @@ class EventDecryptor {
|
||||
* Handle a `MegolmDecryptionError` returned by the rust SDK.
|
||||
*
|
||||
* Fires off a request to the `perSessionBackupDownloader`, if appropriate, and then throws a `DecryptionError`.
|
||||
*
|
||||
* @param event - The event which could not be decrypted.
|
||||
* @param err - The error from the Rust SDK.
|
||||
* @param serverBackupInfo - Details about the current backup from the server. `null` if there is no backup.
|
||||
* `undefined` if our attempt to check failed.
|
||||
*/
|
||||
private onMegolmDecryptionError(event: MatrixEvent, err: RustSdkCryptoJs.MegolmDecryptionError): never {
|
||||
private onMegolmDecryptionError(
|
||||
event: MatrixEvent,
|
||||
err: RustSdkCryptoJs.MegolmDecryptionError,
|
||||
serverBackupInfo: KeyBackupInfo | null | undefined,
|
||||
): never {
|
||||
const content = event.getWireContent();
|
||||
const errorDetails = { session: content.sender_key + "|" + content.session_id };
|
||||
|
||||
// If the error looks like it might be recoverable from backup, queue up a request to try that.
|
||||
if (
|
||||
@@ -1728,9 +1741,42 @@ class EventDecryptor {
|
||||
err.code === RustSdkCryptoJs.DecryptionErrorCode.UnknownMessageIndex
|
||||
) {
|
||||
this.perSessionBackupDownloader.onDecryptionKeyMissingError(event.getRoomId()!, content.session_id!);
|
||||
|
||||
// If the server is telling us our membership at the time the event
|
||||
// was sent, and it isn't "join", we use a different error code.
|
||||
const membership = event.getMembershipAtEvent();
|
||||
if (membership && membership !== KnownMembership.Join && membership !== KnownMembership.Invite) {
|
||||
throw new DecryptionError(
|
||||
DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED,
|
||||
"This message was sent when we were not a member of the room.",
|
||||
errorDetails,
|
||||
);
|
||||
}
|
||||
|
||||
// If the event was sent before this device was created, we use some different error codes.
|
||||
if (event.getTs() <= this.olmMachine.deviceCreationTimeMs) {
|
||||
if (serverBackupInfo === null) {
|
||||
throw new DecryptionError(
|
||||
DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP,
|
||||
"This message was sent before this device logged in, and there is no key backup on the server.",
|
||||
errorDetails,
|
||||
);
|
||||
} else if (!this.perSessionBackupDownloader.isKeyBackupDownloadConfigured()) {
|
||||
throw new DecryptionError(
|
||||
DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED,
|
||||
"This message was sent before this device logged in, and key backup is not working.",
|
||||
errorDetails,
|
||||
);
|
||||
} else {
|
||||
throw new DecryptionError(
|
||||
DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP,
|
||||
"This message was sent before this device logged in. Key backup is working, but we still do not (yet) have the key.",
|
||||
errorDetails,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const errorDetails = { session: content.sender_key + "|" + content.session_id };
|
||||
switch (err.code) {
|
||||
case RustSdkCryptoJs.DecryptionErrorCode.MissingRoomKey:
|
||||
throw new DecryptionError(
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730"
|
||||
integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==
|
||||
|
||||
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.1":
|
||||
version "7.24.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.1.tgz#31c1f66435f2a9c329bb5716a6d6186c516c3742"
|
||||
integrity sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==
|
||||
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a"
|
||||
integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==
|
||||
|
||||
"@babel/compat-data@^7.22.9":
|
||||
version "7.23.5"
|
||||
@@ -83,17 +83,17 @@
|
||||
integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==
|
||||
|
||||
"@babel/core@^7.0.0", "@babel/core@^7.12.10":
|
||||
version "7.24.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3"
|
||||
integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717"
|
||||
integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.2.0"
|
||||
"@babel/code-frame" "^7.24.2"
|
||||
"@babel/generator" "^7.24.1"
|
||||
"@babel/generator" "^7.24.4"
|
||||
"@babel/helper-compilation-targets" "^7.23.6"
|
||||
"@babel/helper-module-transforms" "^7.23.3"
|
||||
"@babel/helpers" "^7.24.1"
|
||||
"@babel/parser" "^7.24.1"
|
||||
"@babel/helpers" "^7.24.4"
|
||||
"@babel/parser" "^7.24.4"
|
||||
"@babel/template" "^7.24.0"
|
||||
"@babel/traverse" "^7.24.1"
|
||||
"@babel/types" "^7.24.0"
|
||||
@@ -160,10 +160,10 @@
|
||||
"@jridgewell/trace-mapping" "^0.3.17"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.24.1":
|
||||
version "7.24.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.1.tgz#e67e06f68568a4ebf194d1c6014235344f0476d0"
|
||||
integrity sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==
|
||||
"@babel/generator@^7.24.1", "@babel/generator@^7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498"
|
||||
integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.24.0"
|
||||
"@jridgewell/gen-mapping" "^0.3.5"
|
||||
@@ -221,10 +221,10 @@
|
||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.24.1":
|
||||
version "7.24.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz#db58bf57137b623b916e24874ab7188d93d7f68f"
|
||||
integrity sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==
|
||||
"@babel/helper-create-class-features-plugin@^7.24.1", "@babel/helper-create-class-features-plugin@^7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz#c806f73788a6800a5cfbbc04d2df7ee4d927cce3"
|
||||
integrity sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.22.5"
|
||||
"@babel/helper-environment-visitor" "^7.22.20"
|
||||
@@ -427,10 +427,10 @@
|
||||
"@babel/traverse" "^7.22.15"
|
||||
"@babel/types" "^7.22.15"
|
||||
|
||||
"@babel/helpers@^7.24.1":
|
||||
version "7.24.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.1.tgz#183e44714b9eba36c3038e442516587b1e0a1a94"
|
||||
integrity sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==
|
||||
"@babel/helpers@^7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6"
|
||||
integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==
|
||||
dependencies:
|
||||
"@babel/template" "^7.24.0"
|
||||
"@babel/traverse" "^7.24.1"
|
||||
@@ -480,10 +480,18 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.3.tgz#0ce0be31a4ca4f1884b5786057cadcb6c3be58f9"
|
||||
integrity sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==
|
||||
|
||||
"@babel/parser@^7.24.0", "@babel/parser@^7.24.1":
|
||||
version "7.24.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.1.tgz#1e416d3627393fab1cb5b0f2f1796a100ae9133a"
|
||||
integrity sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==
|
||||
"@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88"
|
||||
integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==
|
||||
|
||||
"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz#6125f0158543fb4edf1c22f322f3db67f21cb3e1"
|
||||
integrity sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==
|
||||
dependencies:
|
||||
"@babel/helper-environment-visitor" "^7.22.20"
|
||||
"@babel/helper-plugin-utils" "^7.24.0"
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1":
|
||||
version "7.24.1"
|
||||
@@ -736,10 +744,10 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.0"
|
||||
|
||||
"@babel/plugin-transform-block-scoping@^7.24.1":
|
||||
version "7.24.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.1.tgz#27af183d7f6dad890531256c7a45019df768ac1f"
|
||||
integrity sha512-h71T2QQvDgM2SmT29UYU6ozjMlAt7s7CSs5Hvy8f8cf/GM/Z4a2zMfN+fjVGaieeCrXR3EdQl6C4gQG+OgmbKw==
|
||||
"@babel/plugin-transform-block-scoping@^7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz#28f5c010b66fbb8ccdeef853bef1935c434d7012"
|
||||
integrity sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.0"
|
||||
|
||||
@@ -751,12 +759,12 @@
|
||||
"@babel/helper-create-class-features-plugin" "^7.24.1"
|
||||
"@babel/helper-plugin-utils" "^7.24.0"
|
||||
|
||||
"@babel/plugin-transform-class-static-block@^7.24.1":
|
||||
version "7.24.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.1.tgz#4e37efcca1d9f2fcb908d1bae8b56b4b6e9e1cb6"
|
||||
integrity sha512-FUHlKCn6J3ERiu8Dv+4eoz7w8+kFLSyeVG4vDAikwADGjUCoHw/JHokyGtr8OR4UjpwPVivyF+h8Q5iv/JmrtA==
|
||||
"@babel/plugin-transform-class-static-block@^7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz#1a4653c0cf8ac46441ec406dece6e9bc590356a4"
|
||||
integrity sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.24.1"
|
||||
"@babel/helper-create-class-features-plugin" "^7.24.4"
|
||||
"@babel/helper-plugin-utils" "^7.24.0"
|
||||
"@babel/plugin-syntax-class-static-block" "^7.14.5"
|
||||
|
||||
@@ -1120,14 +1128,15 @@
|
||||
"@babel/helper-plugin-utils" "^7.24.0"
|
||||
|
||||
"@babel/preset-env@^7.12.11":
|
||||
version "7.24.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.3.tgz#f3f138c844ffeeac372597b29c51b5259e8323a3"
|
||||
integrity sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA==
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.4.tgz#46dbbcd608771373b88f956ffb67d471dce0d23b"
|
||||
integrity sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==
|
||||
dependencies:
|
||||
"@babel/compat-data" "^7.24.1"
|
||||
"@babel/compat-data" "^7.24.4"
|
||||
"@babel/helper-compilation-targets" "^7.23.6"
|
||||
"@babel/helper-plugin-utils" "^7.24.0"
|
||||
"@babel/helper-validator-option" "^7.23.5"
|
||||
"@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.4"
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.1"
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.1"
|
||||
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.1"
|
||||
@@ -1154,9 +1163,9 @@
|
||||
"@babel/plugin-transform-async-generator-functions" "^7.24.3"
|
||||
"@babel/plugin-transform-async-to-generator" "^7.24.1"
|
||||
"@babel/plugin-transform-block-scoped-functions" "^7.24.1"
|
||||
"@babel/plugin-transform-block-scoping" "^7.24.1"
|
||||
"@babel/plugin-transform-block-scoping" "^7.24.4"
|
||||
"@babel/plugin-transform-class-properties" "^7.24.1"
|
||||
"@babel/plugin-transform-class-static-block" "^7.24.1"
|
||||
"@babel/plugin-transform-class-static-block" "^7.24.4"
|
||||
"@babel/plugin-transform-classes" "^7.24.1"
|
||||
"@babel/plugin-transform-computed-properties" "^7.24.1"
|
||||
"@babel/plugin-transform-destructuring" "^7.24.1"
|
||||
@@ -1231,9 +1240,9 @@
|
||||
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.8.4":
|
||||
version "7.24.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.1.tgz#431f9a794d173b53720e69a6464abc6f0e2a5c57"
|
||||
integrity sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd"
|
||||
integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
@@ -1385,7 +1394,7 @@
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@eslint-community/regexpp@^4.5.1":
|
||||
"@eslint-community/regexpp@^4.10.0":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
|
||||
integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
|
||||
@@ -1826,10 +1835,10 @@
|
||||
semver "^7.3.5"
|
||||
which "^4.0.0"
|
||||
|
||||
"@npmcli/map-workspaces@3.0.4":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz#15ad7d854292e484f7ba04bc30187a8320dba799"
|
||||
integrity sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg==
|
||||
"@npmcli/map-workspaces@^3.0.4":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-3.0.6.tgz#27dc06c20c35ef01e45a08909cab9cb3da08cea6"
|
||||
integrity sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==
|
||||
dependencies:
|
||||
"@npmcli/name-from-folder" "^2.0.0"
|
||||
glob "^10.2.2"
|
||||
@@ -1841,17 +1850,17 @@
|
||||
resolved "https://registry.yarnpkg.com/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz#c44d3a7c6d5c184bb6036f4d5995eee298945815"
|
||||
integrity sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==
|
||||
|
||||
"@npmcli/package-json@5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-5.0.0.tgz#77d0f8b17096763ccbd8af03b7117ba6e34d6e91"
|
||||
integrity sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==
|
||||
"@npmcli/package-json@^5.0.0":
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-5.0.3.tgz#d8a922fcd5abe27a8b0ed619beddfef0f44e614e"
|
||||
integrity sha512-cgsjCvld2wMqkUqvY+SZI+1ZJ7umGBYc9IAKfqJRKJCcs7hCQYxScUgdsyrRINk3VmdCYf9TXiLBHQ6ECTxhtg==
|
||||
dependencies:
|
||||
"@npmcli/git" "^5.0.0"
|
||||
glob "^10.2.2"
|
||||
hosted-git-info "^7.0.0"
|
||||
json-parse-even-better-errors "^3.0.0"
|
||||
normalize-package-data "^6.0.0"
|
||||
proc-log "^3.0.0"
|
||||
proc-log "^4.0.0"
|
||||
semver "^7.5.3"
|
||||
|
||||
"@npmcli/promise-spawn@^7.0.0":
|
||||
@@ -1905,10 +1914,10 @@
|
||||
dependencies:
|
||||
"@pnpm/types" "9.4.2"
|
||||
|
||||
"@pnpm/error@5.0.3":
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@pnpm/error/-/error-5.0.3.tgz#4dbb9f4acb0b30c373b3ca5024cdf495f03f4380"
|
||||
integrity sha512-ONJU5cUeoeJSy50qOYsMZQHTA/9QKmGgh1ATfEpCLgtbdwqUiwD9MxHNeXUYYI/pocBCz6r1ZCFqiQvO+8SUKA==
|
||||
"@pnpm/error@5.0.2":
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@pnpm/error/-/error-5.0.2.tgz#153d18fe9eeaeb02e48e9dc45b042f4c962b3822"
|
||||
integrity sha512-0TEm+tWNYm+9uh6DSKyRbv8pv/6b4NL0PastLvMxIoqZbBZ5Zj1cYi332R9xsSUi31ZOsu2wpgn/bC7DA9hrjg==
|
||||
dependencies:
|
||||
"@pnpm/constants" "7.1.1"
|
||||
|
||||
@@ -1944,13 +1953,13 @@
|
||||
semver "^7.3.5"
|
||||
validate-npm-package-name "^4.0.0"
|
||||
|
||||
"@pnpm/npm-resolver@18.1.1":
|
||||
version "18.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@pnpm/npm-resolver/-/npm-resolver-18.1.1.tgz#64a259825db6dc4e4615f5b67464c1cd174850bf"
|
||||
integrity sha512-NptzncmMD5ZMimbjWkGpMzuBRhlCY+sh7mzypPdBOTNlh5hmEQe/VaRKjNK4V9/b0C/llElkvIePL6acybu86w==
|
||||
"@pnpm/npm-resolver@18.1.0":
|
||||
version "18.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@pnpm/npm-resolver/-/npm-resolver-18.1.0.tgz#bbafcdf88391ee84e2dc78c2b599b54dbbc8f8e3"
|
||||
integrity sha512-fUYKX/iHiHldL0VRVvkQI35YK2jWhZEkPO6rrGke8309+LKAo12v833nBttMDpQrtHefmqhB4mhCzQq6L2Xqmg==
|
||||
dependencies:
|
||||
"@pnpm/core-loggers" "9.0.6"
|
||||
"@pnpm/error" "5.0.3"
|
||||
"@pnpm/error" "5.0.2"
|
||||
"@pnpm/fetching-types" "5.0.0"
|
||||
"@pnpm/graceful-fs" "3.2.0"
|
||||
"@pnpm/resolve-workspace-range" "5.0.1"
|
||||
@@ -1990,15 +1999,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@pnpm/types/-/types-9.4.2.tgz#0a34c3c41d5452461d8d8958374a727f9c46cfb2"
|
||||
integrity sha512-g1hcF8Nv4gd76POilz9gD4LITAPXOe5nX4ijgr8ixCbLQZfcpYiMfJ+C1RlMNRUDo8vhlNB4O3bUlxmT6EAQXA==
|
||||
|
||||
"@pnpm/workspace.pkgs-graph@^2.0.14":
|
||||
version "2.0.16"
|
||||
resolved "https://registry.yarnpkg.com/@pnpm/workspace.pkgs-graph/-/workspace.pkgs-graph-2.0.16.tgz#8f5fa108a34aa584c24ab825be6b42f99a06a155"
|
||||
integrity sha512-WNsDLkDKm7/eht91s/Iif9ELLabdshAIqpH3svCwdp/xiRxGumfUWkCCeCODjLbBCQehrsl3ugSsboIvk0xiPw==
|
||||
"@pnpm/workspace.pkgs-graph@2.0.14":
|
||||
version "2.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@pnpm/workspace.pkgs-graph/-/workspace.pkgs-graph-2.0.14.tgz#3ea12b8d95987e64bc98876422ea7ad578cd022a"
|
||||
integrity sha512-SBXXyWDkPEoaLTjLRyQzRHoBYH+P0NLcIjX1yPUxuJiMTvGOMzjpLWTuxYNVe/P0V0VQMrjpJFaJPjlViNLhzg==
|
||||
dependencies:
|
||||
"@pnpm/npm-package-arg" "^1.0.0"
|
||||
"@pnpm/npm-resolver" "18.1.1"
|
||||
"@pnpm/npm-resolver" "18.1.0"
|
||||
"@pnpm/resolve-workspace-range" "5.0.1"
|
||||
"@pnpm/types" "9.4.2"
|
||||
ramda "npm:@pnpm/ramda@0.28.1"
|
||||
|
||||
"@sinclair/typebox@^0.24.1":
|
||||
@@ -2172,7 +2180,7 @@
|
||||
"@types/tough-cookie" "*"
|
||||
parse5 "^7.0.0"
|
||||
|
||||
"@types/json-schema@^7.0.12", "@types/json-schema@^7.0.9":
|
||||
"@types/json-schema@^7.0.12", "@types/json-schema@^7.0.15":
|
||||
version "7.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||
@@ -2195,9 +2203,9 @@
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/node@18":
|
||||
version "18.19.28"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.28.tgz#c64a2c992c8ebbf61100a4570e4eebc1934ae030"
|
||||
integrity sha512-J5cOGD9n4x3YGgVuaND6khm5x07MMdAKkRyXnjVR6KFhLMNh2yONGiP7Z+4+tBOt5mK+GvDTiacTOVGGpqiecw==
|
||||
version "18.19.31"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.31.tgz#b7d4a00f7cb826b60a543cebdbda5d189aaecdcd"
|
||||
integrity sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
@@ -2221,12 +2229,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/sdp-transform/-/sdp-transform-2.4.9.tgz#26ef39f487a6909b0512f580b80920a366b27f52"
|
||||
integrity sha512-bVr+/OoZZy7wrHlNcEAAa6PAgKA4BoXPYVN2EijMC5WnGgQ4ZEuixmKnVs2roiAvr7RhIFVH17QD27cojgIZCg==
|
||||
|
||||
"@types/semver@^7.3.12":
|
||||
version "7.5.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.7.tgz#326f5fdda70d13580777bcaa1bc6fa772a5aef0e"
|
||||
integrity sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==
|
||||
|
||||
"@types/semver@^7.5.0":
|
||||
"@types/semver@^7.5.0", "@types/semver@^7.5.8":
|
||||
version "7.5.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
|
||||
integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==
|
||||
@@ -2264,89 +2267,76 @@
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^7.0.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz#1dc52fe48454d5b54be2d5f089680452f1628a5a"
|
||||
integrity sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.0.tgz#bf34a02f221811505b8bf2f31060c8560c1bb0a3"
|
||||
integrity sha512-GJWR0YnfrKnsRoluVO3PRb9r5aMZriiMMM/RHj5nnTrBy1/wIgk76XCtCKcnXGjpZQJQRFtGV9/0JJ6n30uwpQ==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.5.1"
|
||||
"@typescript-eslint/scope-manager" "7.5.0"
|
||||
"@typescript-eslint/type-utils" "7.5.0"
|
||||
"@typescript-eslint/utils" "7.5.0"
|
||||
"@typescript-eslint/visitor-keys" "7.5.0"
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "7.7.0"
|
||||
"@typescript-eslint/type-utils" "7.7.0"
|
||||
"@typescript-eslint/utils" "7.7.0"
|
||||
"@typescript-eslint/visitor-keys" "7.7.0"
|
||||
debug "^4.3.4"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^5.2.4"
|
||||
ignore "^5.3.1"
|
||||
natural-compare "^1.4.0"
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/parser@^7.0.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.5.0.tgz#1eeff36309ac2253c905dd4a88b4b71b72a358ed"
|
||||
integrity sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.7.0.tgz#6b1b3ce76c5de002c43af8ae933613b0f2b4bcc6"
|
||||
integrity sha512-fNcDm3wSwVM8QYL4HKVBggdIPAy9Q41vcvC/GtDobw3c4ndVT3K6cqudUmjHPw8EAp4ufax0o58/xvWaP2FmTg==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "7.5.0"
|
||||
"@typescript-eslint/types" "7.5.0"
|
||||
"@typescript-eslint/typescript-estree" "7.5.0"
|
||||
"@typescript-eslint/visitor-keys" "7.5.0"
|
||||
"@typescript-eslint/scope-manager" "7.7.0"
|
||||
"@typescript-eslint/types" "7.7.0"
|
||||
"@typescript-eslint/typescript-estree" "7.7.0"
|
||||
"@typescript-eslint/visitor-keys" "7.7.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.62.0":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c"
|
||||
integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==
|
||||
"@typescript-eslint/scope-manager@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1"
|
||||
integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.62.0"
|
||||
"@typescript-eslint/visitor-keys" "5.62.0"
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz#70f0a7361430ab1043a5f97386da2a0d8b2f4d56"
|
||||
integrity sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==
|
||||
"@typescript-eslint/scope-manager@7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.7.0.tgz#3f0db079b275bb8b0cb5be7613fb3130cfb5de77"
|
||||
integrity sha512-/8INDn0YLInbe9Wt7dK4cXLDYp0fNHP5xKLHvZl3mOT5X17rK/YShXaiNmorl+/U4VKCVIjJnx4Ri5b0y+HClw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "7.5.0"
|
||||
"@typescript-eslint/visitor-keys" "7.5.0"
|
||||
"@typescript-eslint/types" "7.7.0"
|
||||
"@typescript-eslint/visitor-keys" "7.7.0"
|
||||
|
||||
"@typescript-eslint/type-utils@7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz#a8faa403232da3a3901655387c7082111f692cf9"
|
||||
integrity sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==
|
||||
"@typescript-eslint/type-utils@7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.7.0.tgz#36792ff4209a781b058de61631a48df17bdefbc5"
|
||||
integrity sha512-bOp3ejoRYrhAlnT/bozNQi3nio9tIgv3U5C0mVDdZC7cpcQEDZXvq8inrHYghLVwuNABRqrMW5tzAv88Vy77Sg==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "7.5.0"
|
||||
"@typescript-eslint/utils" "7.5.0"
|
||||
"@typescript-eslint/typescript-estree" "7.7.0"
|
||||
"@typescript-eslint/utils" "7.7.0"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/types@5.62.0":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f"
|
||||
integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==
|
||||
"@typescript-eslint/types@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d"
|
||||
integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==
|
||||
|
||||
"@typescript-eslint/types@7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.5.0.tgz#0a284bcdef3cb850ec9fd57992df9f29d6bde1bc"
|
||||
integrity sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==
|
||||
"@typescript-eslint/types@7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.7.0.tgz#23af4d24bf9ce15d8d301236e3e3014143604f27"
|
||||
integrity sha512-G01YPZ1Bd2hn+KPpIbrAhEWOn5lQBrjxkzHkWvP6NucMXFtfXoevK82hzQdpfuQYuhkvFDeQYbzXCjR1z9Z03w==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.62.0":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b"
|
||||
integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==
|
||||
"@typescript-eslint/typescript-estree@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46"
|
||||
integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.62.0"
|
||||
"@typescript-eslint/visitor-keys" "5.62.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz#aa5031c511874420f6b5edd90f8e4021525ee776"
|
||||
integrity sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "7.5.0"
|
||||
"@typescript-eslint/visitor-keys" "7.5.0"
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
@@ -2354,49 +2344,62 @@
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
|
||||
"@typescript-eslint/utils@7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.5.0.tgz#bbd963647fbbe9ffea033f42c0fb7e89bb19c858"
|
||||
integrity sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==
|
||||
"@typescript-eslint/typescript-estree@7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.0.tgz#b5dd6383b4c6a852d7b256a37af971e8982be97f"
|
||||
integrity sha512-8p71HQPE6CbxIBy2kWHqM1KGrC07pk6RJn40n0DSc6bMOBBREZxSDJ+BmRzc8B5OdaMh1ty3mkuWRg4sCFiDQQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "7.7.0"
|
||||
"@typescript-eslint/visitor-keys" "7.7.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
minimatch "^9.0.4"
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/utils@7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.7.0.tgz#3d2b6606a60ac34f3c625facfb3b3ab7e126f58d"
|
||||
integrity sha512-LKGAXMPQs8U/zMRFXDZOzmMKgFv3COlxUQ+2NMPhbqgVm6R1w+nU1i4836Pmxu9jZAuIeyySNrN/6Rc657ggig==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@types/json-schema" "^7.0.15"
|
||||
"@types/semver" "^7.5.8"
|
||||
"@typescript-eslint/scope-manager" "7.7.0"
|
||||
"@typescript-eslint/types" "7.7.0"
|
||||
"@typescript-eslint/typescript-estree" "7.7.0"
|
||||
semver "^7.6.0"
|
||||
|
||||
"@typescript-eslint/utils@^6.0.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134"
|
||||
integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@types/json-schema" "^7.0.12"
|
||||
"@types/semver" "^7.5.0"
|
||||
"@typescript-eslint/scope-manager" "7.5.0"
|
||||
"@typescript-eslint/types" "7.5.0"
|
||||
"@typescript-eslint/typescript-estree" "7.5.0"
|
||||
"@typescript-eslint/scope-manager" "6.21.0"
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
||||
semver "^7.5.4"
|
||||
|
||||
"@typescript-eslint/utils@^5.10.0":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86"
|
||||
integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==
|
||||
"@typescript-eslint/visitor-keys@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47"
|
||||
integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@types/semver" "^7.3.12"
|
||||
"@typescript-eslint/scope-manager" "5.62.0"
|
||||
"@typescript-eslint/types" "5.62.0"
|
||||
"@typescript-eslint/typescript-estree" "5.62.0"
|
||||
eslint-scope "^5.1.1"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.62.0":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e"
|
||||
integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.62.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz#8abcac66f93ef20b093e87a400c2d21e3a6d55ee"
|
||||
integrity sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "7.5.0"
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.0.tgz#950148cf1ac11562a2d903fdf7acf76714a2dc9e"
|
||||
integrity sha512-h0WHOj8MhdhY8YWkzIF30R379y0NqyOHExI9N9KCzvmu05EgG4FumeYa3ccfKUSphyWkWQE1ybVrgz/Pbam6YA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "7.7.0"
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
|
||||
"@ungap/structured-clone@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
|
||||
@@ -2886,9 +2889,9 @@ caniuse-lite@^1.0.30001565:
|
||||
integrity sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==
|
||||
|
||||
caniuse-lite@^1.0.30001587:
|
||||
version "1.0.30001605"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz#ca12d7330dd8bcb784557eb9aa64f0037870d9d6"
|
||||
integrity sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ==
|
||||
version "1.0.30001610"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001610.tgz#2f44ed6e21d359e914271ae35b68903632628ccf"
|
||||
integrity sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==
|
||||
|
||||
chalk@5.2.0:
|
||||
version "5.2.0"
|
||||
@@ -3300,9 +3303,9 @@ electron-to-chromium@^1.4.601:
|
||||
integrity sha512-2yszojF7vIZ68adIOvzV4bku8OZad9w5H9xF3ZAMZjPuOjBarlflUkjN6DggdV+L71WZuKUfKUhov/34+G5QHg==
|
||||
|
||||
electron-to-chromium@^1.4.668:
|
||||
version "1.4.723"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.723.tgz#827da30c96b316684d352c3d81430029df01bb8e"
|
||||
integrity sha512-rxFVtrMGMFROr4qqU6n95rUi9IlfIm+lIAt+hOToy/9r6CDv0XiEcQdC3VP71y1pE5CFTzKV0RvxOGYCPWWHPw==
|
||||
version "1.4.737"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.737.tgz#3a774a58e04980741f65d440f5fdf57af18b6dde"
|
||||
integrity sha512-QvLTxaLHKdy5YxvixAw/FfHq2eWLUL9KvsPjp0aHK1gI5d3EDuDgITkvj0nFO2c6zUY3ZqVAJQiBYyQP9tQpfw==
|
||||
|
||||
emittery@^0.13.1:
|
||||
version "0.13.1"
|
||||
@@ -3519,17 +3522,17 @@ eslint-plugin-import@^2.26.0:
|
||||
semver "^6.3.1"
|
||||
tsconfig-paths "^3.15.0"
|
||||
|
||||
eslint-plugin-jest@^27.1.6:
|
||||
version "27.9.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz#7c98a33605e1d8b8442ace092b60e9919730000b"
|
||||
integrity sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==
|
||||
eslint-plugin-jest@^28.0.0:
|
||||
version "28.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz#863e2b2bda95eb41981ba9bcf4c44f57dce40a73"
|
||||
integrity sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "^5.10.0"
|
||||
"@typescript-eslint/utils" "^6.0.0"
|
||||
|
||||
eslint-plugin-jsdoc@^48.0.0:
|
||||
version "48.2.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.2.tgz#eefdc5e3bb3cea957b66dd4817e9de30930b5270"
|
||||
integrity sha512-S0Gk+rpT5w/ephKCncUY7kUsix9uE4B9XI8D/fS1/26d8okE+vZsuG1IvIt4B6sJUdQqsnzi+YXfmh+HJG11CA==
|
||||
version "48.2.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.3.tgz#0188d17c7a4aa7185416556589e71a954b343ecd"
|
||||
integrity sha512-r9DMAmFs66VNvNqRLLjHejdnJtILrt3xGi+Qx0op0oRfFGVpOR1Hb3BC++MacseHx93d8SKYPhyrC9BS7Os2QA==
|
||||
dependencies:
|
||||
"@es-joy/jsdoccomment" "~0.42.0"
|
||||
are-docs-informative "^0.0.2"
|
||||
@@ -3554,10 +3557,10 @@ eslint-plugin-tsdoc@^0.2.17:
|
||||
"@microsoft/tsdoc" "0.14.2"
|
||||
"@microsoft/tsdoc-config" "0.16.2"
|
||||
|
||||
eslint-plugin-unicorn@^51.0.0:
|
||||
version "51.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz#3641c5e110324c3739d6cb98fc1b99ada39f477b"
|
||||
integrity sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==
|
||||
eslint-plugin-unicorn@^52.0.0:
|
||||
version "52.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-52.0.0.tgz#c7a559edd52e3932cf2b3a05c3b0efc604c1eeb8"
|
||||
integrity sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.22.20"
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
@@ -3581,7 +3584,7 @@ eslint-rule-composer@^0.3.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9"
|
||||
integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==
|
||||
|
||||
eslint-scope@5.1.1, eslint-scope@^5.1.1:
|
||||
eslint-scope@5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
|
||||
integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
|
||||
@@ -4258,7 +4261,7 @@ identity-function@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/identity-function/-/identity-function-1.0.0.tgz#bea1159f0985239be3ca348edf40ce2f0dd2c21d"
|
||||
integrity sha512-kNrgUK0qI+9qLTBidsH85HjDLpZfrrS0ElquKKe/fJFdB3D7VeKdXXEvOPDUHSHOzdZKCAAaQIWWyp0l2yq6pw==
|
||||
|
||||
ignore@^5.1.8, ignore@^5.2.0, ignore@^5.2.4:
|
||||
ignore@^5.1.8, ignore@^5.2.0, ignore@^5.3.1:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
|
||||
integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==
|
||||
@@ -5168,17 +5171,17 @@ kleur@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||
|
||||
knip@^4.0.1:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/knip/-/knip-4.6.0.tgz#8857616ff89e81e404f07b1a92ad64f43b55dc70"
|
||||
integrity sha512-6slzggzmyAuvtr97nH56ob1RNlkrG2dGF7yn8PJ/LIF8bPsoM93TRNLWTbmuOg4/E1CImilSX4qy9fok0AKJyA==
|
||||
knip@^5.0.0:
|
||||
version "5.9.4"
|
||||
resolved "https://registry.yarnpkg.com/knip/-/knip-5.9.4.tgz#62d95ce61e3a37a692d4be317f6614effa569e0e"
|
||||
integrity sha512-33TM8bSHxMMoj+wP9lzjUkIIEfpXaZsLWMYRCoHdbmYnl2HKPMNijcYTxwi1omRROobXrR/VJyH2ZsYOKM1jtg==
|
||||
dependencies:
|
||||
"@ericcornelissen/bash-parser" "0.5.2"
|
||||
"@nodelib/fs.walk" "2.0.0"
|
||||
"@npmcli/map-workspaces" "3.0.4"
|
||||
"@npmcli/package-json" "5.0.0"
|
||||
"@npmcli/map-workspaces" "^3.0.4"
|
||||
"@npmcli/package-json" "^5.0.0"
|
||||
"@pnpm/logger" "5.0.0"
|
||||
"@pnpm/workspace.pkgs-graph" "^2.0.14"
|
||||
"@pnpm/workspace.pkgs-graph" "2.0.14"
|
||||
"@snyk/github-codeowners" "1.1.0"
|
||||
"@types/picomatch" "2.3.3"
|
||||
easy-table "1.2.0"
|
||||
@@ -5188,14 +5191,14 @@ knip@^4.0.1:
|
||||
micromatch "4.0.5"
|
||||
minimist "1.2.8"
|
||||
picocolors "1.0.0"
|
||||
picomatch "4.0.1"
|
||||
picomatch "^4.0.1"
|
||||
pretty-ms "9.0.0"
|
||||
semver "7.6.0"
|
||||
resolve "1.22.8"
|
||||
smol-toml "1.1.4"
|
||||
strip-json-comments "5.0.1"
|
||||
summary "2.1.0"
|
||||
zod "3.22.4"
|
||||
zod-validation-error "3.0.0"
|
||||
zod "^3.22.4"
|
||||
zod-validation-error "^3.0.3"
|
||||
|
||||
leven@^3.1.0:
|
||||
version "3.1.0"
|
||||
@@ -5479,7 +5482,7 @@ min-indent@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
|
||||
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
|
||||
|
||||
minimatch@9.0.3, minimatch@^9.0.1, minimatch@^9.0.3:
|
||||
minimatch@9.0.3, minimatch@^9.0.1:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
|
||||
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
|
||||
@@ -5493,7 +5496,7 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^9.0.0:
|
||||
minimatch@^9.0.0, minimatch@^9.0.3, minimatch@^9.0.4:
|
||||
version "9.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51"
|
||||
integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==
|
||||
@@ -5900,16 +5903,16 @@ picocolors@1.0.0, picocolors@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
picomatch@4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.1.tgz#68c26c8837399e5819edce48590412ea07f17a07"
|
||||
integrity sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
picomatch@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab"
|
||||
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
|
||||
|
||||
pidtree@0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c"
|
||||
@@ -5978,6 +5981,11 @@ proc-log@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8"
|
||||
integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==
|
||||
|
||||
proc-log@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-4.1.0.tgz#ab6c1552b454e9e467cb58119179e4557d109b34"
|
||||
integrity sha512-dmQ2iPw2nJMi9/4dpaG1wd0m1GE+K5kW7RGbjy5hoEEGnhPIzsm+klBO5RGGdcoYbWsNtU2KSNAdEldts+icLg==
|
||||
|
||||
promise-inflight@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||
@@ -6203,19 +6211,19 @@ resolve.exports@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800"
|
||||
integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==
|
||||
|
||||
resolve@^1.10.0, resolve@^1.20.0:
|
||||
version "1.22.4"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34"
|
||||
integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==
|
||||
resolve@1.22.8, resolve@^1.14.2, resolve@^1.22.4:
|
||||
version "1.22.8"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
|
||||
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
|
||||
dependencies:
|
||||
is-core-module "^2.13.0"
|
||||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
resolve@^1.14.2, resolve@^1.22.4:
|
||||
version "1.22.8"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
|
||||
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
|
||||
resolve@^1.10.0, resolve@^1.20.0:
|
||||
version "1.22.4"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34"
|
||||
integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==
|
||||
dependencies:
|
||||
is-core-module "^2.13.0"
|
||||
path-parse "^1.0.7"
|
||||
@@ -6329,18 +6337,18 @@ sdp-transform@^2.14.1:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||
|
||||
semver@7.6.0, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.4.0, semver@^7.5.4, semver@^7.6.0:
|
||||
semver@^6.1.0, semver@^6.3.0, semver@^6.3.1:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.5, semver@^7.4.0, semver@^7.5.4, semver@^7.6.0:
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
|
||||
integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
semver@^6.1.0, semver@^6.3.0, semver@^6.3.1:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
semver@^7.5.3:
|
||||
version "7.5.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||
@@ -6535,7 +6543,16 @@ string-length@^4.0.1:
|
||||
char-regex "^1.0.2"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
"string-width-cjs@npm:string-width@^4.2.0":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
@@ -6786,7 +6803,7 @@ tr46@~0.0.3:
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||
|
||||
ts-api-utils@^1.0.1:
|
||||
ts-api-utils@^1.0.1, ts-api-utils@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1"
|
||||
integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==
|
||||
@@ -6820,23 +6837,11 @@ tsconfig-paths@^3.15.0:
|
||||
minimist "^1.2.6"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^1.8.1:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.0.0, tslib@^2.4.0, tslib@^2.6.1, tslib@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||
|
||||
tsutils@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
|
||||
integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
|
||||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
type-check@^0.4.0, type-check@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
|
||||
@@ -6919,9 +6924,9 @@ typedoc-plugin-coverage@^3.0.0:
|
||||
integrity sha512-fxeJRrxQR3yM/aFZU7mOuatgRCztiMCbeNiCRVZKY6VNgOcVMC1HS+ZfZnlbLLteUOdeWleSQ6yntuipz5zi6A==
|
||||
|
||||
typedoc-plugin-mdn-links@^3.0.3:
|
||||
version "3.1.18"
|
||||
resolved "https://registry.yarnpkg.com/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-3.1.18.tgz#736df9b90245583aa00d726d6eec474e0cbec37a"
|
||||
integrity sha512-BGzSUEHT15o3g2Q1q/5tBQufAM+yqJNwU1aUmYZC9qbfCS1I5qyEkmoxZ9ks2Z3TwPTZ8PMfIKd2vq5/0nmLnw==
|
||||
version "3.1.21"
|
||||
resolved "https://registry.yarnpkg.com/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-3.1.21.tgz#bde151737be1c301117329aacf930cf701cfd860"
|
||||
integrity sha512-RbGsC6RFDp4u5dhSj+e489dXCDM6CIBin6lluPdpwOZ5C7kCbrvIyh8tSnNd8/vLoSPYVj2wwTu6HbRSjI8fLQ==
|
||||
|
||||
typedoc-plugin-missing-exports@^2.0.0:
|
||||
version "2.2.0"
|
||||
@@ -6929,9 +6934,9 @@ typedoc-plugin-missing-exports@^2.0.0:
|
||||
integrity sha512-2+XR1IcyQ5UwXZVJe9NE6HrLmNufT9i5OwoIuuj79VxuA3eYq+Y6itS9rnNV1D7UeQnUSH8kISYD73gHE5zw+w==
|
||||
|
||||
typedoc@^0.25.10:
|
||||
version "0.25.12"
|
||||
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.12.tgz#f73f0a8d3731d418cc604d4230f95a857799e27a"
|
||||
integrity sha512-F+qhkK2VoTweDXd1c42GS/By2DvI2uDF4/EpG424dTexSHdtCH52C6IcAvMA6jR3DzAWZjHpUOW+E02kyPNUNw==
|
||||
version "0.25.13"
|
||||
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.13.tgz#9a98819e3b2d155a6d78589b46fa4c03768f0922"
|
||||
integrity sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==
|
||||
dependencies:
|
||||
lunr "^2.3.9"
|
||||
marked "^4.3.0"
|
||||
@@ -6939,9 +6944,9 @@ typedoc@^0.25.10:
|
||||
shiki "^0.14.7"
|
||||
|
||||
typescript@^5.3.3:
|
||||
version "5.4.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff"
|
||||
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
|
||||
version "5.4.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
|
||||
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
|
||||
|
||||
unbox-primitive@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -7343,12 +7348,12 @@ yocto-queue@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
zod-validation-error@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.0.0.tgz#69dee45a03ccf9739456bddb50b4d27f121c6f45"
|
||||
integrity sha512-x+agsJJG9rvC7axF0xqTEdZhJkLHyIZkdOAWDJSmwGPzxNHMHwtU6w2yDOAAP6yuSfTAUhAMJRBfhVGY64ySEQ==
|
||||
zod-validation-error@^3.0.3:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.1.0.tgz#ce6b74a67b1b28cbbc41f890e88b2778f856e1fe"
|
||||
integrity sha512-zujS6HqJjMZCsvjfbnRs7WI3PXN39ovTcY1n8a+KTm4kOH0ZXYsNiJkH1odZf4xZKMkBDL7M2rmQ913FCS1p9w==
|
||||
|
||||
zod@3.22.4:
|
||||
zod@^3.22.4:
|
||||
version "3.22.4"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
|
||||
integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==
|
||||
|
||||
Reference in New Issue
Block a user