feat(desktop): Settings › Integrations lists every integration, with Linear's row moved there (integrations 2/5)

Merged
DA
7d ago
+500-296

What

Dean: "…let's pull out the settings to a new Integrations tab." This is integrations 2/5, stacked on #2319.

  1. Settings › Integrations is a new page in the settings sidebar, right after Coding agents, with a plug glyph (Tabler's plug-connected, drawn in our stroke). It is SETTINGS_PAGE.INTEGRATIONS in @sidecar/settings and PRODUCT_SETTINGS_VIEW.INTEGRATIONS in the counting vocabulary, which the total Record bridge requires.

  2. Each provider gets a row, modelled on the API keys page: its mark and name, one line saying what connecting it lets the agents do, and the action at the row's end.

    • Connect.
    • Disconnect, with a check beside the name, which asks first in place.
    • Connect again when a sign-in is under way or expired; the line then says which.
    • Muted Not available text, with no button, on a deployment with no connector for the provider.

    A note above the rows says whose account the agents use. Signed out, the page asks for a sign-in and asks the host nothing.

  3. Linear's row moves off General. The Account section is back to who is signed in, Sign out, and Delete account.

  4. Search: each provider is found on the Integrations page ("linear", "issues tracker", "connect", "integration", "mcp").

  5. Shared modules for the composer's MCP-server button (being built in another workspace):

    • renderer/integration-statuses.ts: useIntegrationStatuses(), one read for every provider, on mount and on window focus.
    • renderer/integration-marks.tsx: IntegrationMark({ provider }), tracing the generated LINEAR_PATH.
  6. The agents' "connect it in…" sentences and PRIVACY.md now name Settings › Integrations.

Tests

  • integrations-page.test.ts:
    • A disconnected account is offered Connect, which sends the browser and reads the outcome when the window comes back.
    • Disconnect asks first.
    • A browser that could not open says so.
    • Expired offers Connect again; unavailable offers nothing.
    • An expired read that lands mid-Connect stays expired.
    • Signed out asks nothing.
  • settings-search.test.ts: "issues tracker" finds Linear on the Integrations page, and nothing while signed out.
  • desktop-settings.test.ts: the sidebar's page list now ends with Integrations.

./scripts/check.sh exits 0.

Screenshots

These are the renderer's real markup: the jsdom-mounted DesktopSettings on the Integrations page, wrapped in the built styles.css and rendered in headless Chrome on Linux.

LightDark
Connected
Disconnected
No connector on this deployment

Mac validation

CI could not verify the Mac UI: no CI job builds the Mac app. ./scripts/verify.sh was not run, because this is a Linux cloud VM; LUKE-159 is the manual Mac pass.

🤖 Generated with Claude Code