chore(upstream): report to commetchat/commet — encrypted-call io.element.call.encryption_keys omits member.id (and other interop notes vs matrix-js-sdk) #136

Open
opened 2026-09-27 23:04:54 +00:00 by robocub · 0 comments
Member

Tracking issue for reporting a Commet interop gap upstream to commetchat/commet. Same convention as #128: the operator files this by hand — agent PRs/issues to upstream are out.

Context: #135 (our side is fixed by tolerating the missing field; this is about Commet matching the de-facto wire format so other strict consumers don't hit the same silent drop).

What to report

Title suggestion: MatrixRTC encrypted calls: io.element.call.encryption_keys to-device content omits member.id (present in matrix-js-sdk's EncryptionKeysToDeviceEventContent)

Where (as of 1111f25, 2026-09-24): commet/lib/client/matrix/components/voip_room/matrix_livekit_encryption_key_provider.dart, sendKeyToParticipants:

"member": {"claimed_device_id": room.client.deviceID!},

Reference shape — matrix-js-sdk src/matrixrtc/types.ts:

export interface EncryptionKeysToDeviceEventContent {
    keys: { index: number; key: string };
    member: { id: string; claimed_device_id: string };
    room_id: string;
    session: { application: string; call_id: string; scope: string };
    sent_ts?: number;
}

member.id is the sender's call-membership id (js-sdk uses its membership UUID; the _m.call state-key form "{device_id}_m.call" is what we send). Suggest Commet include it — e.g. the same value it already puts in its own org.matrix.msc3401.call.member state key after the _{userId}_ prefix.

Impact observed: a consumer that models the content strictly (our Rust bridge did) rejects Commet's key and the Commet caller is heard by nobody on that consumer, with no visible error on either side. Element Call is lenient, so Commet↔EC works and the gap goes unnoticed.

Other notes worth mentioning in the same report (from reading the file; not blocking us):

  • sendKeyToParticipants only targets devices already present in room.client.userDeviceKeys — a member whose device keys haven't been fetched yet gets no key until the next membership-triggered rotateKeys().
  • onSync rotates on every membership change 16 ms later, and createNewKey(waitBeforeUsingKey: true) starts encrypting with the new index after a fixed 5 s regardless of delivery.
  • Receive side installs keys by senderId:claimed_device_id without checking room_id/session — fine for us, but worth knowing when comparing behaviours.

Done when

  • Issue filed on commetchat/commet by the operator (paste link here).
  • Optional: verify against a Commet build that includes member.id — our log should then show member_id=<value> instead of member_id=-.
Tracking issue for reporting a Commet interop gap upstream to **commetchat/commet**. Same convention as #128: the operator files this by hand — agent PRs/issues to upstream are out. Context: #135 (our side is fixed by tolerating the missing field; this is about Commet matching the de-facto wire format so other strict consumers don't hit the same silent drop). ## What to report **Title suggestion:** *MatrixRTC encrypted calls: `io.element.call.encryption_keys` to-device content omits `member.id` (present in matrix-js-sdk's `EncryptionKeysToDeviceEventContent`)* **Where** (as of `1111f25`, 2026-09-24): `commet/lib/client/matrix/components/voip_room/matrix_livekit_encryption_key_provider.dart`, `sendKeyToParticipants`: ```dart "member": {"claimed_device_id": room.client.deviceID!}, ``` **Reference shape** — matrix-js-sdk `src/matrixrtc/types.ts`: ```ts export interface EncryptionKeysToDeviceEventContent { keys: { index: number; key: string }; member: { id: string; claimed_device_id: string }; room_id: string; session: { application: string; call_id: string; scope: string }; sent_ts?: number; } ``` `member.id` is the sender's call-membership id (js-sdk uses its membership UUID; the `_m.call` state-key form `"{device_id}_m.call"` is what we send). Suggest Commet include it — e.g. the same value it already puts in its own `org.matrix.msc3401.call.member` state key after the `_{userId}_` prefix. **Impact observed:** a consumer that models the content strictly (our Rust bridge did) rejects Commet's key and the Commet caller is heard by nobody on that consumer, with no visible error on either side. Element Call is lenient, so Commet↔EC works and the gap goes unnoticed. **Other notes worth mentioning in the same report** (from reading the file; not blocking us): - `sendKeyToParticipants` only targets devices already present in `room.client.userDeviceKeys` — a member whose device keys haven't been fetched yet gets no key until the next membership-triggered `rotateKeys()`. - `onSync` rotates on every membership change 16 ms later, and `createNewKey(waitBeforeUsingKey: true)` starts encrypting with the new index after a fixed 5 s regardless of delivery. - Receive side installs keys by `senderId:claimed_device_id` without checking `room_id`/`session` — fine for us, but worth knowing when comparing behaviours. ## Done when - [ ] Issue filed on commetchat/commet by the operator (paste link here). - [ ] Optional: verify against a Commet build that includes `member.id` — our log should then show `member_id=<value>` instead of `member_id=-`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nether/nether-voicebridge#136
No description provided.