Skip to content

feat(linear): add multi-workspace support - #30314

Draft
smorin wants to merge 8 commits into
raycast:mainfrom
smorin:feat/linear-multi-workspace
Draft

smorin wants to merge 8 commits into
raycast:mainfrom
smorin:feat/linear-multi-workspace

Conversation

@smorin

@smorin smorin commented Aug 18, 2026

Copy link
Copy Markdown

Description

Adds multi-workspace support to the Linear extension: connect any number of workspaces
(including the same workspace under two accounts), switch via a consistent pattern on
every surface (list dropdowns, a form field, a dedicated Create Issue for Myself in
Workspace quick command plus a one-shot workspace argument on Quick Add Comment), a
new Manage Workspaces command, an aggregated menu bar, and workspace-routable AI tools
with a new get-workspaces tool. The quick commands surface their target via a live
root-search subtitle (hidden for single-workspace users).

Single-workspace users see no behavior change: every switcher is invisible until a
second workspace is connected, and an existing login is adopted silently (no re-auth).
The only visible additions are the new Manage Workspaces and Create Issue for Myself
in Workspace commands and an optional workspace argument on Quick Add Comment.

Closes #24297. Supersedes the PAT-based approach in #25646 — this stays entirely on
Raycast's OAuth proxy and token storage.

Approach

  • One OAuth token-storage slot per (workspace, account) pair via per-entry providerIds
    (linear-ws-<orgId>-<userId>); the existing linear slot is adopted unchanged.
  • feat(oauth): allow overriding providerId and extraParameters in built-in OAuthService providers utils#80 adds providerId/extraParameters to OAuthService.linear(); until
    it ships in a release, a small factory (src/api/oauth.ts, AUTH_BACKEND switch)
    constructs the service manually with the same proxy + clientId — the copied constants
    are temporary by design and deleted when the utils option lands.
  • Adding a workspace uses prompt=consent (without it Linear silently skips consent for
    an already-granted app). Linear's consent page has no workspace picker — the grant
    follows the active workspace at linear.app, so the add flow instructs the user to
    switch there first (verified empirically).
  • Background contexts (menu bar) never trigger OAuth flows and use a non-destructive
    token refresh, so a transient network failure can never log a workspace out.
  • Removing a workspace deletes the local token only; Linear-side revocation is opt-in
    (revocation is authorization-scoped and eventually consistent, so an unconditional
    revoke could affect the primary login).
  • AI tools take a per-call workspaceId (each tool call runs in a fresh process, so
    per-call routing is the only reliable design); confirmations resolve the same client
    as executions and display the target workspace.

Testing notes & known limitations

  • The extension declares macOS and Windows support; this change was fully tested on
    macOS only (no Windows hardware available to the author) — flagging for reviewers.
  • Manually verified on macOS across the full design test matrix (two workspaces,
    including the same workspace under two accounts): silent adoption on upgrade, add /
    switch / re-authenticate / log out flows, per-workspace remembered form defaults,
    cross-workspace drafts (draft pins its workspace; the global default is untouched),
    menu-bar aggregation with per-workspace re-auth rows, and AI-tool workspace routing.
  • workspaceId on AI tools is optional by design (absent → active workspace). If the
    model never calls get-workspaces and the user switches the default between a
    confirmation and its execution, routing follows the default; mitigations are the AI
    instructions, a Workspace row on every mutating confirmation, and routing evals.
  • Workspace targeting on the quick commands is a text argument (Raycast argument
    dropdowns require a static list; workspaces are per-user runtime data). It matches
    URL key, account email, or a unique name prefix, and never changes the default
    workspace; Create Issue for Myself is deliberately pegged to the active workspace,
    with the dedicated in-Workspace command for explicit targeting.
  • Pre-existing and deliberately untouched: create-project-update.ts and
    get-initiatives.ts exist undeclared in tools[]; team switch clears the Create
    Issue title via the template-reset effect (upstream behavior, kept for parity).
  • Raycast Settings' extension login-row list does not live-refresh (platform behavior);
    Manage Workspaces is the primary management surface and labels each login row
    (providerName: "Linear — <org>").
  • One narrow known issue kept small on purpose: permanent-vs-transient classification of
    a failed staged-add verification matches on error text ("HTTP 401/403") — an SDK-path
    auth failure in a rare race is treated as transient (retried) rather than permanent.

Screencast

<attach the Manage Workspaces add/switch screencast>

Copilot AI lite review requested due to automatic review settings August 18, 2026 05:12
@raycastbot raycastbot added extension fix / improvement Label for PRs with extension's fix improvements extension: linear Issues related to the linear extension AI Extension platform: macOS platform: Windows labels Aug 18, 2026
@raycastbot

raycastbot commented Aug 18, 2026 •

Copy link
Copy Markdown
Collaborator

Thank you for your first contribution! 🎉

🔔 @thomaslombart @thomaspaulmann @peduarte @pernielsentikaer @clemb8 @jfkisafk @filipszczepanski @JoeBoulton @itsmingjie @xmok @0xdhrv @erikjs14 @alexibuild @samuelkraft you might want to have a look.

You can use this guide to learn how to check out the Pull Request locally in order to test it.

📋 Quick checkout commands
BRANCH="feat/linear-multi-workspace"
FORK_URL="https://github.com/smorin/extensions.git"
EXTENSION_NAME="linear"
REPO_NAME="extensions"

git clone -n --depth=1 --filter=tree:0 -b $BRANCH $FORK_URL
cd $REPO_NAME
git sparse-checkout set --no-cone "extensions/$EXTENSION_NAME"
git checkout
cd "extensions/$EXTENSION_NAME"
npm install && npm run dev

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 15 business days.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds multi-workspace support for the Linear Raycast extension, enabling multiple concurrent OAuth sessions (including same workspace across different accounts) with consistent workspace switching across UI surfaces, menu bar aggregation, and AI tool routing.

Changes:

  • Introduces a workspace registry + per-(workspace, account) OAuth providerId strategy, plus a new Manage Workspaces command.
  • Adds workspace switchers (list dropdown + form field), per-workspace persisted UI defaults, and menu bar unread notifications aggregated across workspaces.
  • Routes AI tools per call via workspaceId, adds get-workspaces, and updates tool auth to be non-interactive.

Reviewed changes

Copilot reviewed 99 out of 99 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
extensions/linear/src/unread-notifications.tsx Aggregates unread notifications across all connected workspaces in the menu bar.
extensions/linear/src/tools/update-project-milestone.ts Adds optional workspaceId routing + non-interactive tool auth.
extensions/linear/src/tools/update-issue.ts Adds optional workspaceId routing + workspace-aware confirmations.
extensions/linear/src/tools/update-document.ts Adds optional workspaceId routing + workspace-aware confirmations.
extensions/linear/src/tools/update-comment.ts Adds optional workspaceId routing + workspace-aware confirmations and attachment uploads.
extensions/linear/src/tools/resolveToolWorkspace.ts Implements per-call workspace routing for AI tools and non-interactive auth wrapper.
extensions/linear/src/tools/remove-label.ts Adds optional workspaceId routing + workspace-aware confirmations.
extensions/linear/src/tools/get-workspaces.ts New tool to list connected workspaces without triggering OAuth.
extensions/linear/src/tools/get-teams.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/get-projects.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/get-project-updates.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/get-project-statuses.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/get-notifications.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/get-members.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/get-labels.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/get-issue-states.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/get-initiatives.ts Adds optional workspaceId routing and exposes API helper with client override.
extensions/linear/src/tools/get-documents.ts Adds optional workspaceId routing and exposes API helper with client override.
extensions/linear/src/tools/get-document-content.ts Adds optional workspaceId routing and exposes API helper with client override.
extensions/linear/src/tools/get-current-user.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/full-text-search-issues.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/formatConfirmation.ts Makes confirmations workspace-aware via explicit client parameter.
extensions/linear/src/tools/filter-issues.ts Adds optional workspaceId routing for AI tools.
extensions/linear/src/tools/create-project-update.ts Adds optional workspaceId routing + workspace-aware confirmations.
extensions/linear/src/tools/create-issue.ts Adds optional workspaceId routing + workspace-aware confirmations.
extensions/linear/src/tools/create-document.ts Adds optional workspaceId routing + workspace-aware confirmations.
extensions/linear/src/tools/create-comment.ts Adds optional workspaceId routing + workspace-aware confirmations and attachment uploads.
extensions/linear/src/tools/add-label.ts Adds optional workspaceId routing + workspace-aware confirmations.
extensions/linear/src/search-issues.tsx Adds workspace dropdown accessory to list search UI.
extensions/linear/src/search-custom-views.tsx Adds workspace dropdown accessory to custom view search UI.
extensions/linear/src/quick-add-comment-to-issue.ts Adds one-shot workspace argument resolution + subtitle refresh mechanism.
extensions/linear/src/notifications.tsx Adds workspace dropdown accessory and makes menu bar refresh best-effort.
extensions/linear/src/manage-workspaces.tsx New UI to add/switch/re-auth/logout workspaces with staging-token recovery.
extensions/linear/src/hooks/useWorkspaceCachedState.ts New helper to scope persisted UI state by workspace key.
extensions/linear/src/hooks/useUsers.ts Scopes cached users queries by workspace.
extensions/linear/src/hooks/useTeams.ts Scopes cached teams queries by workspace.
extensions/linear/src/hooks/useStates.ts Scopes cached workflow states queries by workspace.
extensions/linear/src/hooks/useSearchIssues.ts Scopes cached issue search by workspace.
extensions/linear/src/hooks/useProjects.ts Scopes cached projects pagination by workspace.
extensions/linear/src/hooks/useProjectUpdates.ts Scopes cached project updates by workspace.
extensions/linear/src/hooks/useProjectStatuses.ts Scopes cached project statuses by workspace.
extensions/linear/src/hooks/usePriorities.ts Scopes cached priority values by workspace.
extensions/linear/src/hooks/useNotifications.ts Scopes cached notifications by workspace.
extensions/linear/src/hooks/useMilestones.ts Scopes cached milestones by workspace.
extensions/linear/src/hooks/useMe.ts Scopes cached viewer by workspace.
extensions/linear/src/hooks/useLabels.ts Scopes cached labels by workspace.
extensions/linear/src/hooks/useIssues.ts Scopes cached issue lists by workspace.
extensions/linear/src/hooks/useIssueTemplates.ts Scopes cached issue templates by workspace.
extensions/linear/src/hooks/useIssueDetail.ts Scopes cached issue detail by workspace.
extensions/linear/src/hooks/useIssueComments.ts Scopes cached issue comments by workspace.
extensions/linear/src/hooks/useInitiatives.ts Scopes cached initiatives by workspace.
extensions/linear/src/hooks/useDocuments.ts Scopes cached documents + content by workspace.
extensions/linear/src/hooks/useCycles.ts Scopes cached cycles queries by workspace.
extensions/linear/src/hooks/useCustomViews.ts Scopes cached custom views + issues by workspace.
extensions/linear/src/hooks/useAllWorkspaceNotifications.ts New hook to fetch notifications per workspace for menu bar aggregation.
extensions/linear/src/helpers/workspaceArgument.ts Implements workspace argument matching + command subtitle updates.
extensions/linear/src/helpers/refreshQuickSubtitles.ts Adds best-effort background launches to refresh quick-command subtitles.
extensions/linear/src/helpers/createIssueForMyself.ts Extracts “create issue for myself” into a reusable helper supporting client overrides.
extensions/linear/src/favorites.tsx Adds workspace dropdown and scopes favorites caching by workspace.
extensions/linear/src/created-issues.tsx Adds workspace dropdown accessory.
extensions/linear/src/create-project.tsx Adds draft-time workspace pinning and loading gating for project creation flow.
extensions/linear/src/create-issue.tsx Adds draft-time workspace pinning and loading gating for issue creation flow.
extensions/linear/src/create-issue-for-myself.ts Adds workspace subtitle refresh + workspace-aware auth wrapper.
extensions/linear/src/create-issue-for-myself-in-workspace.ts New quick command to create an issue explicitly in a named workspace.
extensions/linear/src/components/docs/DocumentList.tsx Adds workspace switch section to entity dropdown + per-workspace persisted entity selection.
extensions/linear/src/components/WorkspaceDropdown.tsx New list/form workspace dropdown components + embedded section for existing dropdowns.
extensions/linear/src/components/WorkspaceContext.tsx New context/provider handling workspace switching and remount boundary.
extensions/linear/src/components/View.tsx Wraps commands in WorkspaceProvider and updates auth handling for multi-workspace.
extensions/linear/src/components/ProjectList.tsx Adds workspace switch section to initiative dropdown + per-workspace persisted initiative.
extensions/linear/src/components/ProjectIssues.tsx Scopes milestone filter persistence by workspace.
extensions/linear/src/components/EditIssueForm.tsx Removes storeValue from milestone dropdown (workspace-scoped persistence now handled elsewhere).
extensions/linear/src/components/CreateProjectForm.tsx Adds workspace form field + per-workspace persisted defaults (status/lead).
extensions/linear/src/components/CreateMilestoneForm.tsx Adds per-workspace persisted project selection and removes storeValue.
extensions/linear/src/components/CreateIssueForm.tsx Adds workspace form field + per-workspace persisted defaults with readiness semantics.
extensions/linear/src/assigned-issues.tsx Embeds workspace switch section into view dropdown.
extensions/linear/src/api/workspaces.ts New workspace registry (LocalStorage) with migration/adoption of existing single-login slot.
extensions/linear/src/api/withWorkspaceAuth.ts New wrapper reusing withAccessToken but bootstrapping workspace auth.
extensions/linear/src/api/updateNotification.ts Adds optional client override for workspace routing.
extensions/linear/src/api/updateIssue.ts Adds optional client override for workspace routing.
extensions/linear/src/api/oauth.ts Adds providerId-aware OAuth services + staging token flow + non-destructive refresh.
extensions/linear/src/api/linearClient.ts Reworks client bootstrap/caching for multi-workspace + active workspace snapshot.
extensions/linear/src/api/initiatives.ts Adds optional client override for workspace routing.
extensions/linear/src/api/getTeams.ts Adds optional client override for workspace routing.
extensions/linear/src/api/getProjects.ts Adds optional client override for workspace routing.
extensions/linear/src/api/getNotifications.ts Adds optional client override for workspace routing.
extensions/linear/src/api/getMilestones.ts Adds optional client override for workspace routing.
extensions/linear/src/api/getLabels.ts Adds optional client override for workspace routing.
extensions/linear/src/api/getIssues.ts Adds optional client override for workspace routing for all issue queries.
extensions/linear/src/api/getIssueTemplates.ts Adds optional client override for workspace routing.
extensions/linear/src/api/getCustomViews.ts Adds optional client override for workspace routing.
extensions/linear/src/api/favorites.ts Adds optional client override for workspace routing.
extensions/linear/src/api/documents.ts Adds optional client override for workspace routing.
extensions/linear/src/api/deleteNotification.ts Adds optional client override for workspace routing.
extensions/linear/src/api/createIssue.ts Adds optional client override for workspace routing (issue + sub-issue).
extensions/linear/src/api/attachments.ts Adds optional client override to keep uploads routed to correct workspace.
extensions/linear/src/active-cycle.tsx Adds embedded workspace switching + per-workspace persisted selected team.
extensions/linear/package.json Adds new commands/tools and updates AI instructions + evals for workspace routing.
extensions/linear/README.md Documents multi-workspace usage and new management/switching surfaces.
extensions/linear/CHANGELOG.md Adds changelog entry describing multi-workspace support.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +65 to +87
export async function refreshNonDestructive(
service: OAuthService,
): Promise<{ status: "ok"; accessToken: string } | { status: "failed" }> {
const tokens = await service.client.getTokens();
if (!tokens?.refreshToken) return { status: "failed" };
try {
const response = await fetch(`${LINEAR_PROXY}/refresh-token`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: LINEAR_PROXY_CLIENT_ID,
refresh_token: tokens.refreshToken,
grant_type: "refresh_token",
}),
});
if (!response.ok) return { status: "failed" };
const next = (await response.json()) as { access_token: string; refresh_token?: string; expires_in?: number };
await service.client.setTokens(next);
return { status: "ok", accessToken: next.access_token };
} catch {
return { status: "failed" };
}
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a bug as filed: OAuth.PKCEClient.setTokens accepts TokenSetOptions | TokenResponse, and TokenResponse is the snake_case shape (access_token, refresh_token, expires_in) documented as directly passable in @raycast/api's type definitions. While here, ca9eb8c makes the refresh path keep the stored refresh token when a response omits one, matching @raycast/utils's own refreshTokens behavior.

}
}

if (!teamId) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3981f6e: an empty team list now throws the intended "No team found" error instead of a TypeError from teams[0].id.

Comment on lines +100 to +110
{rows.map((row) => (
<MenuBarExtra.Section
key={entryKey(row.entry)}
{...(multi
? {
title:
row.entry.orgName +
(rows.filter((r) => r.entry.orgId === row.entry.orgId).length > 1 ? ` (${row.entry.userEmail})` : ""),
}
: {})}
>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3981f6e: the per-org entry count is computed once with countBy before rendering.

Comment on lines +263 to +279
async function logOutAll() {
const confirmed = await confirmAlert({
title: "Log Out of All Workspaces?",
message:
"Removes every workspace login from Raycast (tokens are deleted locally; each access token expires at Linear on its own within 24 hours).",
primaryAction: { title: "Log Out of All", style: Alert.ActionStyle.Destructive },
});
if (!confirmed) return;
for (const row of rows) {
const service = getServiceForProviderId(row.entry.providerId, undefined, `Linear — ${row.entry.orgName}`);
await service.client.removeTokens();
await removeWorkspaceEntry({ orgId: row.entry.orgId, userId: row.entry.userId });
}
await showToast({ style: Toast.Style.Success, title: "Logged out of all workspaces" });
refreshQuickCommandSubtitles(); // fire-and-forget: workspace membership changed, subtitles listing "others" are now stale
await reload();
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3981f6e: logOutAll now removes each workspace best-effort inside a try/catch, tracks the failing step like logOut, and reports which workspaces failed in a failure toast.

@greptile-apps

greptile-apps Bot commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds multi-workspace authentication, routing, workspace management, aggregate notifications, and workspace-aware AI tools to the Linear extension. The logout cache fix still permits an in-flight menu-bar refresh to restore a removed workspace’s notification data after invalidation.

  • Adds per-workspace OAuth storage and active-workspace selection across commands and forms.
  • Adds Manage Workspaces, aggregate menu-bar notifications, and workspace-routable AI tools.
  • Adds notification-cache clearing to workspace logout flows, but without an ordering barrier against existing refreshes.

Confidence Score: 3/5

The PR is not yet safe to merge because logout can still leave removed-workspace notification payloads in the unencrypted cache through stale asynchronous writeback.

smorin stated that the notification-cache issue was addressed, but a refresh that captured the workspace before logout can complete after the clear and unconditionally persist the same removed workspace’s rows again.

Files Needing Attention: extensions/linear/src/hooks/useAllWorkspaceNotifications.ts and extensions/linear/src/manage-workspaces.tsx

Security Review

The notification-cache invalidation remains vulnerable to stale asynchronous writeback: a refresh started before logout can persist the removed workspace’s private notification payloads after the cache is cleared.

Important Files Changed

Filename Overview
extensions/linear/src/hooks/useAllWorkspaceNotifications.ts Adds aggregated notification fetching and named caching, but an in-flight request can repopulate removed-workspace rows after logout clears the cache.
extensions/linear/src/manage-workspaces.tsx Adds workspace lifecycle management and cache clearing on logout, but the clear operation does not invalidate notification requests already in progress.
extensions/linear/src/api/workspaces.ts Implements the multi-workspace registry, migration, active-entry selection, and workspace removal primitives.
extensions/linear/src/api/linearClient.ts Adds per-workspace client and token resolution used throughout the extension.
extensions/linear/src/tools/resolveToolWorkspace.ts Routes AI tool calls through the requested connected workspace.
extensions/linear/package.json Registers the workspace-management commands, workspace argument, and workspace-discovery AI tool.
Prompt To Fix All With AI
### Issue 1
extensions/linear/src/hooks/useAllWorkspaceNotifications.ts:63
**Stale refresh restores logged-out data**

If a menu-bar notification refresh overlaps a workspace logout, the request retains the pre-removal registry and `onData` writes its completed rows after `clearWorkspaceNotificationsCache()` runs, restoring the removed workspace’s private notification payloads to the unencrypted cache until a later successful refresh replaces them.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (3): Last reviewed commit: "fix(linear): preserve interrupted worksp..." | Re-trigger Greptile

Comment thread extensions/linear/src/hooks/useAllWorkspaceNotifications.ts Outdated
@0xdhrv 0xdhrv self-assigned this Aug 21, 2026
@smorin

smorin commented Aug 24, 2026

Copy link
Copy Markdown
Author

@0xdhrv thanks for picking it up let me know if you have questions or suggestions

@0xdhrv

0xdhrv commented Aug 25, 2026

Copy link
Copy Markdown
Member

@0xdhrv thanks for picking it up let me know if you have questions or suggestions

Looks good so far, the API team is reviewing the utils changes, once it's done I'll will re-review this

@smorin

smorin commented Aug 25, 2026

Copy link
Copy Markdown
Author

@0xdhrv The design doesn't really immediately take advantage of the útil changes. Built so it works without that. Once those are in can do an update to take advantage of the new auth capabilities

@djshubs

djshubs commented Aug 26, 2026

Copy link
Copy Markdown

@smorin thanks for contributing here. I'd be excited to use it!

@smorin

smorin commented Sep 1, 2026

Copy link
Copy Markdown
Author

@djshubs and @0xdhrv any update on this one?

@0xdhrv 0xdhrv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @smorin 👋

Thanks for the contribution 🔥

Could you look into the suggestions from Greptile?

Also, could you resolve the merge conflict?


I converted this PR into a draft until it's ready for the review, please press the button Ready for review when it's ready and we'll have a look 😊

@0xdhrv
0xdhrv marked this pull request as draft September 2, 2026 11:46
@smorin
smorin force-pushed the feat/linear-multi-workspace branch from 7ca9d40 to ca9eb8c Compare September 2, 2026 20:54
@smorin

smorin commented Sep 2, 2026

Copy link
Copy Markdown
Author

@0xdhrv thanks — both items done: rebased onto main (resolves the conflict, and adapts the multi-workspace routing to the new AI-tool set from #30517: all list/get/save tools now accept workspaceId, and the AI guidance moved into ai.yaml), and every Greptile/Copilot thread is answered inline with a fix or a rationale. Marking ready for review.

@smorin
smorin marked this pull request as ready for review September 2, 2026 20:54
@smorin
smorin requested a review from samuelkraft as a code owner September 2, 2026 20:54
@smorin
smorin requested a review from 0xdhrv September 3, 2026 03:57

@0xdhrv 0xdhrv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi 👋

Thanks for your contribution 💪

I have now tested your extension, and I have some feedback ready for you:

When I tried to login into with my other account into other workspace, I got successfully connected message on the webpage, but I don't see it working meaning, I don't see two workspaces in the list for Manage Workspaces command. I suppose this is related to pending publish of utils changes, but want to confirm, if this is the case?

I'm looking forward to testing this extension again 🔥

Feel free to contact me here or at Slack if you have any questions.

@0xdhrv
0xdhrv marked this pull request as draft September 3, 2026 11:19
@smorin

smorin commented Sep 3, 2026

Copy link
Copy Markdown
Author

Hi 👋

Thanks for your contribution 💪

I have now tested your extension, and I have some feedback ready for you:

When I tried to login into with my other account into other workspace, I got successfully connected message on the webpage, but I don't see it working meaning, I don't see two workspaces in the list for Manage Workspaces command. I suppose this is related to pending publish of utils changes, but want to confirm, if this is the case?

I'm looking forward to testing this extension again 🔥

Feel free to contact me here or at Slack if you have any questions.

Nope, that is a bug of some sort. In this PR, I had a workaround to make it work until the other PR was ready, but built it with a plan to be compatible and switch over once that's ready.

I did the merge, and on my end, I have this working on my end I'll send you a video in slack

@0xdhrv
0xdhrv marked this pull request as ready for review September 7, 2026 07:02
@raycastbot raycastbot added the OP is contributor The OP of the PR is a contributor of the extension label Sep 7, 2026

@pernielsentikaer pernielsentikaer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @smorin 👋

I also just gave it a spin but I'm not able to connect the second one in my end, I just end up in this window after connecting the second workspace

1788765340866.png

Could there be some kind of race condition?


I converted this PR into a draft until it's ready for the review, please press the button Ready for review when it's ready and we'll have a look 😊

@pernielsentikaer
pernielsentikaer marked this pull request as draft September 7, 2026 07:15
@smorin

smorin commented Sep 7, 2026 via email

Copy link
Copy Markdown
Author

@smorin

smorin commented Sep 7, 2026

Copy link
Copy Markdown
Author

@pernielsentikaer messaged you in Slack Community

);
},
[],
{ onData: setCachedRows },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Stale refresh restores logged-out data

If a menu-bar notification refresh overlaps a workspace logout, the request retains the pre-removal registry and onData writes its completed rows after clearWorkspaceNotificationsCache() runs, restoring the removed workspace’s private notification payloads to the unencrypted cache until a later successful refresh replaces them.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/linear/src/hooks/useAllWorkspaceNotifications.ts
Line: 63

Comment:
**Stale refresh restores logged-out data**

If a menu-bar notification refresh overlaps a workspace logout, the request retains the pre-removal registry and `onData` writes its completed rows after `clearWorkspaceNotificationsCache()` runs, restoring the removed workspace’s private notification payloads to the unencrypted cache until a later successful refresh replaces them.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Extension extension fix / improvement Label for PRs with extension's fix improvements extension: linear Issues related to the linear extension OP is contributor The OP of the PR is a contributor of the extension platform: macOS platform: Windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linear Extension: Unable to switch between organizations

6 participants