Skip to content

shortcuts: the host reads the installed applications for the widget - #6

Open
mcouzinet wants to merge 1 commit into
fdussert:mainfrom
mcouzinet:shortcuts-installed-apps
Open

mcouzinet wants to merge 1 commit into
fdussert:mainfrom
mcouzinet:shortcuts-installed-apps

Conversation

@mcouzinet

Copy link
Copy Markdown
Contributor

A shortcut button pointing at an application that is not in the Dock draws the kind's □ glyph instead of the app's icon. The widget has the name the user typed and needs the bundle id the icon is filed under, so loadInstalled() reads /api/apps/installed itself — but a widget's frame is served with connect-src 'none' (WIDGET_CSP), so the request never leaves the page:

Connecting to 'http://127.0.0.1:4242/api/apps/installed' violates the following
Content Security Policy directive: "connect-src 'none'". The action has been blocked.

installed therefore stays empty and only what the Dock has already named resolves to an icon. Same class of bug as the favicons one, and the same shape of fix, one step further along: Fremkit.installedApps() asks the host page, which is the server's own origin, and hands the list back.

  • server/src/bridge/fremkit.js — installedApps(), beside favicon().
  • ui/src/shared/useWidgetBridge.ts — the fremkit:apps case: fetch the route, reply with the list, bridge.noApps when it refuses. No request parameters, so nothing to validate in widgetMessages.ts.
  • widgets/shortcuts/index.html — loadInstalled() asks the bridge; the retry timer, the Dock fallback and the glyph are unchanged. Manifest 1.3.0 → 1.3.1.
  • server/test/shortcuts-widget.test.ts — the widget evaluated for real against stubs: the icon of an undocked application, a name filed under another bundle name (Code.app → com.microsoft.VSCode), the glyph while no answer comes, and the Dock fallback. The first two fail on main.
  • Docs and CHANGELOG.

The route answers { name, bundleId, file } and no filesystem path, so a widget learns nothing here it could not already ask the Dock channel for — but it is one more thing every widget can ask, ungated like favicon(). Happy to put it behind a manifest permission instead if you would rather.

Checked on a real dashboard (second instance, FREMKIT_PORT=4302): Terminal and Sequel Ace, neither of them in the Dock, draw their own icons, and the console is clean.

pnpm typecheck and pnpm test are green (66 server files / 1352 tests, 30 UI files / 382 tests).

🤖 Generated with Claude Code

A button pointing at an application that is not in the Dock has drawn
the kind's glyph rather than its icon. The widget knows the name the
user typed and needs the bundle id the icon is filed under, so it read
`/api/apps/installed` itself — but a widget's frame is served with
`connect-src 'none'`, so that request never left the page: the console
says the connection violates the policy, the list stayed empty, and only
the applications the Dock had already named resolved to an icon.

`Fremkit.installedApps()` asks the host page, which is the server's own
origin, exactly as `Fremkit.favicon()` does one step further along. The
route already answers names and bundle ids without a filesystem path, so
the widget learns nothing it could not have asked for before. When the
answer does not come the Dock match and the glyph still stand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mcouzinet
mcouzinet force-pushed the shortcuts-installed-apps branch from c046c8d to 353f6d0 Compare September 22, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant