feat(lotus): work when served from its own origin (cinny #43)
CI / Build embedded bundle (pull_request) Successful in 3m43s
CI / Publish to Gitea npm registry (pull_request) Skipped

Two things tied EC to the host's origin:

- Widget message check: matrix-widget-api's strictOriginCheck compares
  ev.origin with THIS frame's origin, so on call.chat.lotusguild.org every
  message from chat.lotusguild.org would be dropped and calls would not
  start. restrictToHost() instead requires ev.source === window.parent and
  ev.origin === parentUrl's origin. Same-origin deployments keep working
  (the host origin is our own origin there), and it is stricter than
  before: the sender must also be our parent window.
- Soundboard: the host's blob: clip URL is origin-bound. io.lotus.inject_audio
  now accepts the clip's bytes (`audio`, ArrayBuffer, <= 8 MiB) and prefers
  them over `url`; hosts that only send `url` are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
Lotus CI
2026-09-26 23:24:32 -04:00
co-authored by Claude Opus 5.5
parent 43a5e93c37
commit a93bd9d7d8
5 changed files with 213 additions and 36 deletions
+6 -10
View File
@@ -24,6 +24,7 @@ import { Config } from "./config/Config";
import { seedSettingsFromConfig } from "./settings/settings";
import { ElementCallReactionEventType } from "./reactions";
import { LOTUS_TO_WIDGET_ACTIONS } from "./lotus/lotusActions";
import { restrictToHost } from "./lotus/lotusWidgetOrigin";
// Subset of the actions in element-web
export enum ElementWidgetActions {
@@ -94,16 +95,11 @@ export const initializeWidget = (
const parentOrigin = new URL(parentUrl).origin;
logger.info("Widget API is available");
const api = new WidgetApi(widgetId, parentOrigin);
// [lotus] matrix-widget-api's PostmessageTransport defaults
// strictOriginCheck to false, which would let any frame holding a
// handle to our window post toWidget actions (including the
// io.lotus.* actions below). The Lotus deployment serves EC
// same-origin with the host (cinny loads /public/element-call/index.html),
// so globalThis.origin === parentOrigin and this check passes safely.
// A cross-origin deployment would need to compare ev.origin to
// parentOrigin instead, since strictOriginCheck compares against
// globalThis.origin.
api.transport.strictOriginCheck = true;
// [lotus] Only messages from the host (our parent, at parentUrl's
// origin) reach the widget API. matrix-widget-api's own
// strictOriginCheck compares against THIS frame's origin, so it only
// worked while EC was served from the host's origin (cinny #43).
restrictToHost(api.transport, parentOrigin);
api.requestCapability(MatrixCapabilities.AlwaysOnScreen);
api.requestCapability(MatrixCapabilities.MSC4039DownloadFile);