fix(connected-apps): let remote clients disconnect their own accounts - #1067
Conversation
Issue milind-soni#1048: a paired desktop client could add a connected-app account but had no Disconnect control — the panel hid it behind `connectedAppsMayDisconnect(remoteClient)`, and the companion boundary denied the account DELETE route outright. A user who connected Gmail from a remote client had no way to revoke it. The revocation block predates desktop remote access: it was written for the phone companion, where the boundary deliberately keeps host mutation small. Paired clients may already add accounts (POST .../authorize is allowlisted), so "connectable but never disconnectable" was an asymmetry rather than a safety property — and the environments/session path already permits the same DELETE for admin-scoped remote sessions. - companion/src/routes.ts: allowlist DELETE /api/connectors/:slug/accounts/:accountId. The handler still proves the account belongs to the host's own Composio user before revoking, so a paired device can only remove accounts it could already see and add. The whole-service DELETE stays denied. - PluginsPanel: always render the per-account Disconnect control; drop the remote-client gate and the now-unused connectedAppsMayDisconnect helper. - Tests: update the allowlist contract and drop the obsolete remote-permission test. Verification: pnpm typecheck; pnpm exec vitest run for the touched suites (companion routes, PluginsPanel) — 99/99 pass; full suite 5798 pass, 9 failures are environment-dependent and unrelated (linux-after-install tmpdir, control-omb fake-engine, browser-bundle linux-arm64, engine-install npm PATH).
|
@santhiprakash is attempting to deploy a commit to the SupaMaus Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (4)
💤 Files with no reviewable changes (1)
Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe companion allowlist now permits account-specific connector deletion. The plugins panel renders account disconnection controls for remote clients. Tests cover authorization boundaries, path traversal, connector state handling, and disconnect behavior. ChangesRemote account disconnection
Estimated code review effort: 3 (Moderate) | ~20 minutes Severity of issue fixed: Medium Sequence Diagram(s)sequenceDiagram
participant PluginsPanel
participant CompanionRoutes
participant ConnectedAppServer
PluginsPanel->>CompanionRoutes: DELETE connector account
CompanionRoutes->>ConnectedAppServer: Authorize account deletion
ConnectedAppServer-->>CompanionRoutes: Verify ownership and revoke account
CompanionRoutes-->>PluginsPanel: Return deletion result
Suggested reviewers: Merge Risk: ⚪ Minimal · up to Paired clients can now disconnect individual connected accounts, with ownership checks and whole-service deletion protections preserved. The change is merge-ready. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Refs #1048
What changed
The Connected apps account row now shows its Disconnect button for remote
(desktop companion) clients too, and the companion sidecar allowlists the
per-account route it calls:
companion/src/routes.ts—DELETE /api/connectors/:slug/accounts/:idisadded to
ALLOWED.src/components/PluginsPanel.tsx— the{mayDisconnect && …}gate isremoved (and the now-unused
connectedAppsMayDisconnecthelper with it), soevery listed account offers Disconnect.
Why
A user who connects an account from a paired remote client gets a card that
shows the account but no way to remove it — the UI hid the button and the
companion boundary would have denied the DELETE anyway. The asymmetry was
already there for adding (
POST …/authorizeis allowlisted), so a remoteclient could connect but never disconnect.
The revocation exclusion predates desktop remote access and was scoped to the
phone companion ("a paired phone … never remove one"). Two notes on the
boundary change, for review:
removeAccountstill proves the account belongs to the host's own Composiouser before revoking, so a paired device can only remove accounts it could
already see and add.
DELETE /api/connectors/:slugstays denied; only theper-account route the panel actually calls is opened.
How it was verified
pnpm typecheck— clean.pnpm exec vitest run companion/test/routes.test.ts src/components/PluginsPanel.test.ts src/components/PluginsPanel.i18n.test.ts— 99/99 pass, including the new "allows DELETE …/accounts/:id" case and a path-traversal denial case.pnpm exec vitest run— 5798 pass, 9 unrelated environment-dependent failures (linux-after-install tmpdir, control-omb fake-engine, browser-bundle linux-arm64, engine-install npm PATH).Screenshots (UI changes)
n/a — restores a control that already renders for non-remote clients.
Checklist
pnpm typecheckandpnpm testpass locallydist-server/edits (it's build output)shell: true/ cmd.exe string-buildingSummary by CodeRabbit
New Features
Bug Fixes