open-design/apps
Sid 0701dee9b9
fix(desktop): allow od:// URLs in setWindowOpenHandler so live artifact previews open in child window (#911) (#933)
The Orbit panel's "Open artifact" button is an
`<a target="_blank" href="/api/live-artifacts/.../preview?projectId=...">`.
In packaged Electron builds the renderer is loaded from
`od://app/`, so the relative `href` resolves to
`od://app/api/live-artifacts/.../preview?projectId=...` by the
time `setWindowOpenHandler` sees it.

The existing handler in `apps/desktop/src/main/runtime.ts:300`
runs three checks in order:

  1. `isAllowedChildWindowUrl(url)` → only matched `blob:`
  2. `isHttpUrl(url)` → only matched `http:` / `https:`
  3. fall through → `{ action: "deny" }`

The packaged `od://` scheme matched neither, so the click was
silently dropped — Orbit's "Open artifact" became a no-op for
every desktop user. Dev mode (`http://127.0.0.1:port/`) was
unaffected: its links resolved through the http branch and
opened in the user's external browser via `shell.openExternal`.

Fix: extend `isAllowedChildWindowUrl` to also accept the
packaged `od:` scheme. Electron then opens a child BrowserWindow
that inherits the same protocol registration + preload, so the
live artifact preview HTML (served via the `od://` proxy in
`apps/packaged/src/protocol.ts`) renders in the new window.

Behavior delta:

  - Packaged: click → `od://app/api/.../preview` → child window
    renders the live artifact preview (was: silent no-op).
  - Dev mode: unchanged — link is `http://127.0.0.1:port/...`,
    still routes to `shell.openExternal`.
  - Other links inside the packaged app that still flow to
    `shell.openExternal` (e.g. github.com / external docs):
    unchanged — `od:` is not a wildcard, only the packaged
    scheme passes the allowlist.

Tests: exposed `isHttpUrl` and `isAllowedChildWindowUrl` from
`apps/desktop/src/main/index.ts` (re-exported through
`@open-design/desktop/main`) so the packaged workspace's vitest
can pin both helpers without bringing up Electron. 8 tests
across the negative-guard surface — `od:` allowed, `blob:` still
allowed, `http(s):` NOT allowed by this branch (handled by the
sibling `isHttpUrl` path), `file:`, `javascript:`, `data:`
explicitly NOT allowed.

The pre-existing `apps/packaged/tests/sidecars.test.ts >
adds custom VP_HOME/bin to the packaged PATH builder` failure
is unrelated to this PR — confirmed by stashing the change
and re-running on the bare branch base.

Verified locally:
  - packaged vitest desktop-url-allowlist: 8/8
  - desktop tsc -p tsconfig.json --noEmit: clean
  - packaged tsc -p tsconfig.json --noEmit: clean
  - packaged tsc -p tsconfig.tests.json --noEmit (the CI killer): clean
2026-05-08 22:16:35 +08:00
..
daemon fix: add gpt-5.1 Codex picker options (#946) 2026-05-08 21:37:49 +08:00
desktop fix(desktop): allow od:// URLs in setWindowOpenHandler so live artifact previews open in child window (#911) (#933) 2026-05-08 22:16:35 +08:00
landing-page release: Open Design 0.5.0 (#820) 2026-05-08 00:41:01 +08:00
packaged fix(desktop): allow od:// URLs in setWindowOpenHandler so live artifact previews open in child window (#911) (#933) 2026-05-08 22:16:35 +08:00
web fix(web): confirm before clearing a saved Media provider API key (#875) 2026-05-08 22:15:59 +08:00
AGENTS.md test(e2e): gate beta packaged runtime (#637) 2026-05-06 17:44:29 +08:00