feat(linear): connect & manage Linear from iOS via worker-bounce OAuth#860
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Warning Review limit reached
Next review available in: 2 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (6)
📒 Files selected for processing (19)
✨ Finishing Touches🧪 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 |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1a14f11fe5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Add a settings gear to the mobile Linear pane that lets users connect, reconnect, and disconnect their Linear workspace — mirroring desktop's Settings › Integrations, which the phone previously could only view. Backend (sync): four new CTO sync commands — startLinearMobileOAuth, completeLinearMobileOAuth, setLinearToken, clearLinearToken — advertised as optional mobile capabilities (older brains omit them; iOS feature-detects and degrades gracefully with an "update your Mac" hint). linearOAuthService gains an external-redirect flow (startExternalSession/completeExternalSession) reusing the existing PKCE + token-exchange path with no loopback server; the desktop loopback flow is unchanged. The authorization code is exchanged and the token stored desktop-side — it never leaves the machine. OAuth transport: Linear redirects to the ade-github-webhook-relay Worker (/linear/oauth/callback), which 302-bounces to ade://linear-oauth for ASWebAuthenticationSession to capture. The code is PKCE-bound to a verifier that stays on the desktop. iOS: gear → LinearConnectionScreen (status + org logo, reconnect, machine-wide disconnect confirm); inline-actionable disconnected pane (Sign in with Linear + API-key fallback); all affordances gated on supportsRemoteAction. Desktop LinearSection now renders the workspace logo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@codex review |
1a14f11 to
fe3ad3c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fe3ad3ca12
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ker bounce Address @codex review: - P2: a failed OAuth completion can return connected:true with a failure message (desktop preserves the prior token rather than wiping the UI). The iOS runner treated connected as success and showed a false "Connected" confirmation. Now any non-empty status.message on completion is surfaced as a failure; a genuine success carries no message. - P3: the Worker bounced spaces as "+" (URLSearchParams), which iOS URLComponents leaves intact ("User+declined"). Emit %20 so Linear's user-facing error text stays readable. + worker regression test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Codex Review: Didn't find any major issues. What shall we delve into next? Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Adds a settings gear to the mobile Linear pane so users can connect, reconnect, and disconnect their Linear workspace — mirroring desktop's Settings › Integrations, which the phone could previously only view.
How it works (worker-bounce OAuth)
The phone can't run desktop's loopback OAuth (no local browser+listener). Instead:
cto.startLinearMobileOAuth— desktop mints PKCE verifier+state, returns an authorize URL whoseredirect_uriis theade-github-webhook-relayWorker/linear/oauth/callback.ASWebAuthenticationSession; Linear redirects to the Worker, which 302-bounces toade://linear-oauth(captured in-session).cto.completeLinearMobileOAuth {sessionId, code, state}— desktop validates state, exchanges the code with its held verifier, stores the token.The token never leaves the desktop. The phone only relays a PKCE-bound authorization code, useless without the desktop's verifier. API-key entry (
cto.setLinearToken) and disconnect (cto.clearLinearToken) round out parity.Security / correctness (from /quality)
viewerAllowed: true— invocable by a paired, authenticated controller (the phone), same trust aslanes.create/lanes.delete. (An earlier draft had themviewerAllowed: false, which the sync host rejects for all paired devices → feature-dead; fixed + regression-tested.)supportsRemoteActionand shows an "update your Mac" hint instead of failing.ws://; only the relay path iswss://) — same exposure as all existing sync traffic. The OAuth path is unaffected. Recommend a follow-up to gate API-key entry to encrypted transports or add app-layer encryption for secret-bearing commands.Tests
ade-cli sync 145 (gate contract + reconnect-failure regression), desktop cto OAuth 51, worker route 4, iOS ADETests +2 (legacy-host gating). Docs updated (linear-integration, cto, sync-and-multi-device, ios-companion).
Deploy note
The Linear redirect URI is registered. The Worker route requires a
wrangler deployofapps/webhook-relayfor the live OAuth callback (done as part of shipping).🤖 Generated with Claude Code
Greptile Summary
This PR adds mobile Linear connection management through the iOS companion app. The main changes are:
ade://linear-oauth.Confidence Score: 5/5
Safe to merge with low risk.
The changed paths are well-scoped, keep the token exchange on desktop, validate OAuth state before exchange, and preserve backward compatibility through optional capability detection.
No files require special attention.
What T-Rex did
Important Files Changed
ASWebAuthenticationSessionand desktop completion.Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Phone as iOS Linear pane participant Desktop as ADE desktop sync host participant Linear as Linear OAuth participant Worker as webhook relay Worker Phone->>Desktop: cto.startLinearMobileOAuth Desktop->>Desktop: create session, state, PKCE verifier Desktop-->>Phone: sessionId, authorizeUrl(worker redirect_uri) Phone->>Linear: ASWebAuthenticationSession authorizeUrl Linear-->>Worker: "GET /linear/oauth/callback?code&state" Worker-->>Phone: "302 ade://linear-oauth?code&state" Phone->>Desktop: cto.completeLinearMobileOAuth(sessionId, code, state) Desktop->>Desktop: validate state and lookup PKCE verifier Desktop->>Linear: exchange code + verifier Linear-->>Desktop: access/refresh token Desktop->>Desktop: store token locally Desktop-->>Phone: LinearConnectionStatus%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant Phone as iOS Linear pane participant Desktop as ADE desktop sync host participant Linear as Linear OAuth participant Worker as webhook relay Worker Phone->>Desktop: cto.startLinearMobileOAuth Desktop->>Desktop: create session, state, PKCE verifier Desktop-->>Phone: sessionId, authorizeUrl(worker redirect_uri) Phone->>Linear: ASWebAuthenticationSession authorizeUrl Linear-->>Worker: "GET /linear/oauth/callback?code&state" Worker-->>Phone: "302 ade://linear-oauth?code&state" Phone->>Desktop: cto.completeLinearMobileOAuth(sessionId, code, state) Desktop->>Desktop: validate state and lookup PKCE verifier Desktop->>Linear: exchange code + verifier Linear-->>Desktop: access/refresh token Desktop->>Desktop: store token locally Desktop-->>Phone: LinearConnectionStatusReviews (2): Last reviewed commit: "fix(linear): treat failed mobile reconne..." | Re-trigger Greptile