Update SECURITY.md file to request that vulnerabilities be reported through the GitHub Security Advisories feature in the Penpot repository
Signed-off-by: Madalena Melo <madalena.melo@kaleidos.net>
Preserve real size overrides during variant switches without copying stale absolute composite geometry from the source variant.
Signed-off-by: Codex <codex@openai.com>
Add detection for Safari's webkit-masked-url:// extension URLs and filter
the "Attempting to change value of a readonly property" TypeError to prevent
Safari browser extension errors from being surfaced to users.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
The `update-text-range` event's `watch` method was returning a bare
potok event object (`dwwt/resize-wasm-text-debounce id`) directly
inside `rx/concat`, instead of wrapping it in `rx/of`. This caused
RxJS to throw "You provided an invalid object where a stream was
expected" when a plugin set text fills via the Plugin API.
The fix wraps the event in `rx/of` so it becomes a valid Observable,
matching the pattern used elsewhere in the codebase (e.g.,
`clipboard.cljs` lines 1050/1082 and `texts.cljs` line 1232).
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* 📎 Ignore .iml files (IntelliJ module files)
* 🎉 Enable multi-instance horizontal scaling for MCP server
Allow the MCP server to run as multiple instances behind a plain
round-robin load balancer, removing the previous requirement that a
user's plugin WebSocket and MCP client connection terminate on the same
instance. Behaviour is unchanged when run as a single instance or
without Redis.
Cross-instance MCP sessions: when a request arrives with an
mcp-session-id that was initialised on another instance, the session is
adopted locally instead of rejected. The user token is read from the
query parameter (present on every request, as the configured endpoint
URL is never rewritten), so no shared session store is needed; the
transport is pre-initialised so the SDK's validateSession() accepts it.
Cross-instance task routing: when a Redis URI is configured in
multi-user mode, plugin task requests are routed via Redis pub/sub keyed
by user token. The instance holding a plugin's WebSocket subscribes to
that token's request channel; any instance handling a tool call
publishes the request and awaits the response on a per-request channel.
RedisBridge is a pure transport for the existing serialised
PluginTaskRequest/Response objects. PluginTask is split into an abstract
base plus a local (promise-backed) PluginTask and a RemotePluginTask
whose resolve/reject publish the outcome back over Redis, so the
existing local dispatch and response-correlation paths are reused
unchanged on the executing instance.
Refs #10000