[parked] Matrix 2.0 call membership via MSC4354 sticky events — investigated, deliberately NOT enabled #196

Open
opened 2026-09-17 23:24:14 -04:00 by jared · 0 comments
Owner

Migrated from LOTUS_TODO.md on 2026-09-17 (the file is now reference-only).

[PARKED] Matrix 2.0 call membership — MSC4354 Sticky Events (investigated 2026-07, 3 agents + live infra check)

Move MatrixRTC/Element Call call-membership from state events (MSC3401) to sticky events — the "Matrix 2.0" path. Not a flag flip; a coordinated rollout. Parked deliberately.

Findings:

  • Server (Synapse 1.157.1, LXC 151): msc4354_enabled defaults false. Enabling is low-risk, additive, reversible — schema (sticky_events table) already ships unconditionally, no migration/backfill, all runtime paths flag-gated, residual rows self-expire ≤1h. The one historical /sync EDU-filter bug (#19787) was fixed in 1.155.0; SQLite guard N/A (we're Postgres).
  • The flag alone is a no-op for behavior. Our EC fork (upstream v0.20.1 base, @lotusguild/element-call-embedded, bundled into Cinny at build → fleet upgrades atomically) gates sticky mode behind BOTH server support AND a per-device developer-settings radio (matrix-rtc-mode, defaults Legacy). Enabling the flag only un-greys that radio; no client changes what it sends until a human toggles it.
  • Matrix-layer mixed-mode = safe: js-sdk (v41.6.0) reads + merges sticky and state membership, so cross-mode participants see each other.
  • Open risk before any real rollout: media layer. Sticky mode drops livekit_alias + uses lk-jwt-service /get_token (slot m.call#ROOM); legacy uses /sfu/get (room=roomId). Both endpoints are live on our lk-jwt-service, but whether they resolve to the same LiveKit room is unverified — must confirm with a two-account cross-mode test call (one device Matrix_2_0, one Legacy) before changing the default, else split-at-media.

To actually adopt (future): (1) enable msc4354_enabled: true + restart; (2) two-account media-interop test; (3) if unified, flip EC default mode LegacyCompatibility/Matrix_2_0 in the fork + redeploy; (4) keep legacy fallback during transition. No user benefit until step 3.

[ ] Matrix 2.0 call membership — MSC4354 sticky events (INVESTIGATED 2026-07, deliberately NOT enabled)

3-agent investigation after the 1.157.1 upgrade (EC-fork behavior · Synapse/upstream readiness · client-fleet composition). Conclusion: leave msc4354_enabled OFF for now — enabling it is safe but delivers zero user-visible benefit on its own, and introduces a latent footgun.

Why it's a no-op alone: the EC fork's doesServerSupportUnstableFeature(MSC4354) probe feeds exactly one thing — whether the "Matrix 2.0" radio in Developer Settings is greyed out (DeveloperSettingsTab.tsx:349-353). The real switch is the per-device matrixRTCMode setting (settings.ts:149-152), which defaults to Legacy and never auto-enables. Sticky sending is gated at LocalMember.ts:862 (unstableSendStickyEvents: mode === Matrix_2_0). So flipping the server flag changes nothing any client sends.

Verified safe: Synapse-side is additive and cleanly reversible — the sticky_events schema ships unconditionally (no migration/backfill on enable), every write/read/serialize/replication path is flag-gated, disabling stops it instantly and residual rows self-expire ≤1h. The one relevant bug (#19787 /sync EDU-filter) was fixed in 1.155.0; the SQLite<3.40 guard doesn't apply (we're on PG 17.10). Matrix-layer mixed-mode visibility is safe: js-sdk collectMembersEvents reads both sticky and state membership and merges them, so sticky-mode and legacy-mode participants see each other. Our lk-jwt-service already serves both JWT endpoints (legacy /sfu/get and the sticky-mode /get_token — both probed live, 400-with-validation-error = present). EC is bundled into cinny's build (@lotusguild/element-call-embedded), so the fleet upgrades atomically — the "all EC clients ≥ v0.17.0" precondition is structurally guaranteed for our own users.

The one unresolved risk (blocks a real rollout, not the flag): sticky mode drops livekit_alias and uses /get_token (slot m.call#ROOM) while legacy uses /sfu/get (room=roomId). Whether both resolve to the same LiveKit room is a property of lk-jwt-service, not the client — unverified. If they diverge, cross-mode participants appear in each other's member list but are split at the media layer (silent, no error). Requires a two-account test call (one device on Legacy, one on Matrix 2.0) to confirm before anyone relies on it.

If we ever do this: (1) run the two-account media-interop test; (2) only then consider enabling msc4354_enabled: true in /etc/matrix-synapse/homeserver.yaml (LXC 151) + restart; (3) treat a default-mode change as a separate coordinated EC rollout. MSC4354 is still OPEN upstream (not in FCP, needs-implementation), so this stays experimental regardless.

Do not enable without re-reading the investigation above; revisit when Synapse + Element Call both ship stable support.

_Migrated from `LOTUS_TODO.md` on 2026-09-17 (the file is now reference-only)._ ### [PARKED] Matrix 2.0 call membership — MSC4354 Sticky Events (investigated 2026-07, 3 agents + live infra check) Move MatrixRTC/Element Call call-membership from state events (MSC3401) to **sticky events** — the "Matrix 2.0" path. **Not a flag flip; a coordinated rollout. Parked deliberately.** Findings: - **Server (Synapse 1.157.1, LXC 151):** `msc4354_enabled` defaults `false`. Enabling is **low-risk, additive, reversible** — schema (`sticky_events` table) already ships unconditionally, no migration/backfill, all runtime paths flag-gated, residual rows self-expire ≤1h. The one historical `/sync` EDU-filter bug (#19787) was fixed in 1.155.0; SQLite guard N/A (we're Postgres). - **The flag alone is a no-op for behavior.** Our EC fork (upstream **v0.20.1** base, `@lotusguild/element-call-embedded`, bundled into Cinny at build → fleet upgrades atomically) gates sticky mode behind BOTH server support AND a per-device **developer-settings** radio (`matrix-rtc-mode`, defaults `Legacy`). Enabling the flag only un-greys that radio; no client changes what it sends until a human toggles it. - **Matrix-layer mixed-mode = safe:** js-sdk (v41.6.0) reads + merges sticky and state membership, so cross-mode participants see each other. - **Open risk before any real rollout:** media layer. Sticky mode drops `livekit_alias` + uses lk-jwt-service `/get_token` (slot `m.call#ROOM`); legacy uses `/sfu/get` (`room=roomId`). Both endpoints are **live** on our lk-jwt-service, but whether they resolve to the **same LiveKit room** is unverified — must confirm with a **two-account cross-mode test call** (one device `Matrix_2_0`, one `Legacy`) before changing the default, else split-at-media. To actually adopt (future): (1) enable `msc4354_enabled: true` + restart; (2) two-account media-interop test; (3) if unified, flip EC default mode `Legacy`→`Compatibility`/`Matrix_2_0` in the fork + redeploy; (4) keep legacy fallback during transition. **No user benefit until step 3.** ### [ ] Matrix 2.0 call membership — MSC4354 sticky events (INVESTIGATED 2026-07, deliberately NOT enabled) 3-agent investigation after the 1.157.1 upgrade (EC-fork behavior · Synapse/upstream readiness · client-fleet composition). **Conclusion: leave `msc4354_enabled` OFF for now** — enabling it is safe but delivers **zero user-visible benefit on its own**, and introduces a latent footgun. **Why it's a no-op alone:** the EC fork's `doesServerSupportUnstableFeature(MSC4354)` probe feeds **exactly one thing** — whether the "Matrix 2.0" radio in **Developer Settings** is greyed out (`DeveloperSettingsTab.tsx:349-353`). The real switch is the per-device `matrixRTCMode` setting (`settings.ts:149-152`), which **defaults to `Legacy`** and never auto-enables. Sticky sending is gated at `LocalMember.ts:862` (`unstableSendStickyEvents: mode === Matrix_2_0`). So flipping the server flag changes nothing any client sends. **Verified safe:** Synapse-side is **additive and cleanly reversible** — the `sticky_events` schema ships unconditionally (no migration/backfill on enable), every write/read/serialize/replication path is flag-gated, disabling stops it instantly and residual rows self-expire ≤1h. The one relevant bug (#19787 `/sync` EDU-filter) was fixed in 1.155.0; the SQLite<3.40 guard doesn't apply (we're on PG 17.10). Matrix-layer **mixed-mode visibility is safe**: js-sdk `collectMembersEvents` reads **both** sticky and state membership and merges them, so sticky-mode and legacy-mode participants see each other. Our `lk-jwt-service` already serves **both** JWT endpoints (legacy `/sfu/get` **and** the sticky-mode `/get_token` — both probed live, 400-with-validation-error = present). EC is bundled into cinny's build (`@lotusguild/element-call-embedded`), so the fleet upgrades **atomically** — the "all EC clients ≥ v0.17.0" precondition is structurally guaranteed for our own users. **The one unresolved risk (blocks a real rollout, not the flag):** sticky mode drops `livekit_alias` and uses `/get_token` (slot `m.call#ROOM`) while legacy uses `/sfu/get` (`room=roomId`). **Whether both resolve to the same LiveKit room is a property of lk-jwt-service, not the client** — unverified. If they diverge, cross-mode participants appear in each other's member list but are **split at the media layer** (silent, no error). Requires a **two-account test call** (one device on Legacy, one on Matrix 2.0) to confirm before anyone relies on it. **If we ever do this:** (1) run the two-account media-interop test; (2) only then consider enabling `msc4354_enabled: true` in `/etc/matrix-synapse/homeserver.yaml` (LXC 151) + restart; (3) treat a default-mode change as a separate coordinated EC rollout. MSC4354 is still **OPEN upstream** (not in FCP, `needs-implementation`), so this stays experimental regardless. **Do not enable** without re-reading the investigation above; revisit when Synapse + Element Call both ship stable support.
jared added the priority: lowarea: callsresearch labels 2026-09-17 23:24:14 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#196