fix(web): allow removing stale Connect environments - #4968

Closed
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments
Closed

fix(web): allow removing stale Connect environments#4968
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments

Conversation

@soestin

@soestinsoestin commented Jul 30, 2026

Copy link
Copy Markdown

Problem

T3 Connect environments discovered through the relay only offered Connect. If the original machine was lost or rebuilt, users could not unlink its stale relay record because t3 connect unlink always targets the machine running the command.

Fix

  • add a Remove action to relay-discovered environment rows
  • require destructive confirmation that identifies the environment by label and ID
  • call the existing authenticated relay unlinkEnvironment operation
  • refresh discovery and report success or trace-aware failure
  • cover the direct relay unlink request with a focused test

This stays web-only; desktop inherits the web surface. It does not add a new relay contract or expand the CLI.

Fixes#4965.

Validation

  • vp test run src/cloud/linkEnvironment.test.ts --project unit --passWithNoTests — 10 tests passed
  • pnpm typecheck in apps/web
  • targeted vp lint for the four changed files
  • pnpm build in apps/web

UI evidence

Before — existing connected environment

Before: existing connected environment

After — stale environment can be removed

After: stale environment row with Remove action

Confirmation

Confirmation dialog identifies the environment before unlinking

Generated with GPT-5.6-sol through the T3 Code Codex harness.

Note

Add Remove button to Connect environment list to unlink stale relay environments

  • Adds unlinkRelayEnvironmentFromCloud in linkEnvironment.ts that calls the relay client's unlinkEnvironment method via a DELETE request to /v1/client/environment-links/:environmentId.
  • Adds an unlinkRelayEnvironment atom command in linkEnvironmentAtoms.ts that serializes execution per environmentId.
  • Updates CloudEnvironmentConnectList.tsx to show a destructive 'Remove' button per row; clicking it opens a confirmation dialog, then calls the unlink command, refreshes the list, and shows a success or error toast.

Macroscope summarized 902a37c.


Note

Medium Risk
Changes account-linked environment records via the relay API with destructive UI; scope is web-only and reuses existing unlink contracts rather than new auth paths.

Overview
Users can unlink stale T3 Connect environments from relay discovery when the original machine is gone—without running unlink on that host.

Relay-discovered rows that are not already saved now show Remove next to Connect. Remove opens a confirmation dialog (label + environment ID), then calls the existing authenticated relay unlinkEnvironment path via new unlinkRelayEnvironmentFromCloud and the unlinkRelayEnvironment atom command. On success the list refreshes and a toast confirms; failures surface trace-aware errors. Saved/connected rows still only show the disabled connection state—no Remove there.

A unit test asserts the direct relay DELETE to /v1/client/environment-links/:id with the Clerk bearer token.

Reviewed by Cursor Bugbot for commit 902a37c. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc124ac-bd39-4d4d-874f-1fa9b12afb9d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
@StiensWout

Copy link
Copy Markdown
Contributor

already exists in #4844

@soestin
soestin marked this pull request as ready for review July 30, 2026 11:14
@soestin

Copy link
Copy Markdown
Author

Closing as a duplicate of #4844. Thanks for pointing this out.

@soestinsoestin closed this Jul 30, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:902a37c54d

ℹ️ 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".

setRemovingEnvironmentId(null);
if (result._tag === "Success") {
setPendingRemoval(null);
await refreshRelayEnvironments();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force a post-delete discovery refresh

When Remove is clicked while the initial discovery is still checking environment statuses, this call joins that existing refresh because relayEnvironmentDiscovery.refresh is single-flight. That refresh fetched its environment list before the DELETE, so it completes with the removed record still in state; this is especially likely for an inaccessible environment whose status check takes time. The success toast then appears while the stale row remains until a later manual or lifecycle refresh. Queue a new refresh after the active one, or remove the environment from discovery state after a successful unlink.

Useful? React with 👍 / 👎.

@cursorcursorBot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

</p>
</div>
</div>
{savedConnection ? (

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.

Confirm dialog drops on refresh

Medium Severity

The environment removal confirmation AlertDialog is only rendered when the environment list is not empty. During a discovery refresh in standalone mode, if the environment list temporarily clears, early returns will unmount the dialog even if pendingRemoval is set. This causes the confirmation to vanish mid-flow and potentially reappear for a stale environment.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability to remove stale environments, including new API calls, UI components, and confirmation dialogs. Additionally, two unresolved review comments identify potential bugs in state management (stale data after deletion, dialog disappearing during refresh). New features with open bug findings warrant human review.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow removing stale/offline T3 Connect environments without access to the original machine

2 participants

@soestin@StiensWout
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(web): allow removing stale Connect environments - #4968

Closed
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments
Closed

fix(web): allow removing stale Connect environments#4968
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments

Conversation

@soestin

@soestinsoestin commented Jul 30, 2026

Copy link
Copy Markdown

Problem

T3 Connect environments discovered through the relay only offered Connect. If the original machine was lost or rebuilt, users could not unlink its stale relay record because t3 connect unlink always targets the machine running the command.

Fix

  • add a Remove action to relay-discovered environment rows
  • require destructive confirmation that identifies the environment by label and ID
  • call the existing authenticated relay unlinkEnvironment operation
  • refresh discovery and report success or trace-aware failure
  • cover the direct relay unlink request with a focused test

This stays web-only; desktop inherits the web surface. It does not add a new relay contract or expand the CLI.

Fixes#4965.

Validation

  • vp test run src/cloud/linkEnvironment.test.ts --project unit --passWithNoTests — 10 tests passed
  • pnpm typecheck in apps/web
  • targeted vp lint for the four changed files
  • pnpm build in apps/web

UI evidence

Before — existing connected environment

Before: existing connected environment

After — stale environment can be removed

After: stale environment row with Remove action

Confirmation

Confirmation dialog identifies the environment before unlinking

Generated with GPT-5.6-sol through the T3 Code Codex harness.

Note

Add Remove button to Connect environment list to unlink stale relay environments

  • Adds unlinkRelayEnvironmentFromCloud in linkEnvironment.ts that calls the relay client's unlinkEnvironment method via a DELETE request to /v1/client/environment-links/:environmentId.
  • Adds an unlinkRelayEnvironment atom command in linkEnvironmentAtoms.ts that serializes execution per environmentId.
  • Updates CloudEnvironmentConnectList.tsx to show a destructive 'Remove' button per row; clicking it opens a confirmation dialog, then calls the unlink command, refreshes the list, and shows a success or error toast.

Macroscope summarized 902a37c.


Note

Medium Risk
Changes account-linked environment records via the relay API with destructive UI; scope is web-only and reuses existing unlink contracts rather than new auth paths.

Overview
Users can unlink stale T3 Connect environments from relay discovery when the original machine is gone—without running unlink on that host.

Relay-discovered rows that are not already saved now show Remove next to Connect. Remove opens a confirmation dialog (label + environment ID), then calls the existing authenticated relay unlinkEnvironment path via new unlinkRelayEnvironmentFromCloud and the unlinkRelayEnvironment atom command. On success the list refreshes and a toast confirms; failures surface trace-aware errors. Saved/connected rows still only show the disabled connection state—no Remove there.

A unit test asserts the direct relay DELETE to /v1/client/environment-links/:id with the Clerk bearer token.

Reviewed by Cursor Bugbot for commit 902a37c. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc124ac-bd39-4d4d-874f-1fa9b12afb9d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
@StiensWout

Copy link
Copy Markdown
Contributor

already exists in #4844

@soestin
soestin marked this pull request as ready for review July 30, 2026 11:14
@soestin

Copy link
Copy Markdown
Author

Closing as a duplicate of #4844. Thanks for pointing this out.

@soestinsoestin closed this Jul 30, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:902a37c54d

ℹ️ 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".

setRemovingEnvironmentId(null);
if (result._tag === "Success") {
setPendingRemoval(null);
await refreshRelayEnvironments();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force a post-delete discovery refresh

When Remove is clicked while the initial discovery is still checking environment statuses, this call joins that existing refresh because relayEnvironmentDiscovery.refresh is single-flight. That refresh fetched its environment list before the DELETE, so it completes with the removed record still in state; this is especially likely for an inaccessible environment whose status check takes time. The success toast then appears while the stale row remains until a later manual or lifecycle refresh. Queue a new refresh after the active one, or remove the environment from discovery state after a successful unlink.

Useful? React with 👍 / 👎.

@cursorcursorBot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

</p>
</div>
</div>
{savedConnection ? (

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.

Confirm dialog drops on refresh

Medium Severity

The environment removal confirmation AlertDialog is only rendered when the environment list is not empty. During a discovery refresh in standalone mode, if the environment list temporarily clears, early returns will unmount the dialog even if pendingRemoval is set. This causes the confirmation to vanish mid-flow and potentially reappear for a stale environment.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability to remove stale environments, including new API calls, UI components, and confirmation dialogs. Additionally, two unresolved review comments identify potential bugs in state management (stale data after deletion, dialog disappearing during refresh). New features with open bug findings warrant human review.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow removing stale/offline T3 Connect environments without access to the original machine

2 participants

@soestin@StiensWout
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(web): allow removing stale Connect environments - #4968

Closed
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments
Closed

fix(web): allow removing stale Connect environments#4968
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments

Conversation

@soestin

@soestinsoestin commented Jul 30, 2026

Copy link
Copy Markdown

Problem

T3 Connect environments discovered through the relay only offered Connect. If the original machine was lost or rebuilt, users could not unlink its stale relay record because t3 connect unlink always targets the machine running the command.

Fix

  • add a Remove action to relay-discovered environment rows
  • require destructive confirmation that identifies the environment by label and ID
  • call the existing authenticated relay unlinkEnvironment operation
  • refresh discovery and report success or trace-aware failure
  • cover the direct relay unlink request with a focused test

This stays web-only; desktop inherits the web surface. It does not add a new relay contract or expand the CLI.

Fixes#4965.

Validation

  • vp test run src/cloud/linkEnvironment.test.ts --project unit --passWithNoTests — 10 tests passed
  • pnpm typecheck in apps/web
  • targeted vp lint for the four changed files
  • pnpm build in apps/web

UI evidence

Before — existing connected environment

Before: existing connected environment

After — stale environment can be removed

After: stale environment row with Remove action

Confirmation

Confirmation dialog identifies the environment before unlinking

Generated with GPT-5.6-sol through the T3 Code Codex harness.

Note

Add Remove button to Connect environment list to unlink stale relay environments

  • Adds unlinkRelayEnvironmentFromCloud in linkEnvironment.ts that calls the relay client's unlinkEnvironment method via a DELETE request to /v1/client/environment-links/:environmentId.
  • Adds an unlinkRelayEnvironment atom command in linkEnvironmentAtoms.ts that serializes execution per environmentId.
  • Updates CloudEnvironmentConnectList.tsx to show a destructive 'Remove' button per row; clicking it opens a confirmation dialog, then calls the unlink command, refreshes the list, and shows a success or error toast.

Macroscope summarized 902a37c.


Note

Medium Risk
Changes account-linked environment records via the relay API with destructive UI; scope is web-only and reuses existing unlink contracts rather than new auth paths.

Overview
Users can unlink stale T3 Connect environments from relay discovery when the original machine is gone—without running unlink on that host.

Relay-discovered rows that are not already saved now show Remove next to Connect. Remove opens a confirmation dialog (label + environment ID), then calls the existing authenticated relay unlinkEnvironment path via new unlinkRelayEnvironmentFromCloud and the unlinkRelayEnvironment atom command. On success the list refreshes and a toast confirms; failures surface trace-aware errors. Saved/connected rows still only show the disabled connection state—no Remove there.

A unit test asserts the direct relay DELETE to /v1/client/environment-links/:id with the Clerk bearer token.

Reviewed by Cursor Bugbot for commit 902a37c. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc124ac-bd39-4d4d-874f-1fa9b12afb9d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
@StiensWout

Copy link
Copy Markdown
Contributor

already exists in #4844

@soestin
soestin marked this pull request as ready for review July 30, 2026 11:14
@soestin

Copy link
Copy Markdown
Author

Closing as a duplicate of #4844. Thanks for pointing this out.

@soestinsoestin closed this Jul 30, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:902a37c54d

ℹ️ 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".

setRemovingEnvironmentId(null);
if (result._tag === "Success") {
setPendingRemoval(null);
await refreshRelayEnvironments();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force a post-delete discovery refresh

When Remove is clicked while the initial discovery is still checking environment statuses, this call joins that existing refresh because relayEnvironmentDiscovery.refresh is single-flight. That refresh fetched its environment list before the DELETE, so it completes with the removed record still in state; this is especially likely for an inaccessible environment whose status check takes time. The success toast then appears while the stale row remains until a later manual or lifecycle refresh. Queue a new refresh after the active one, or remove the environment from discovery state after a successful unlink.

Useful? React with 👍 / 👎.

@cursorcursorBot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

</p>
</div>
</div>
{savedConnection ? (

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.

Confirm dialog drops on refresh

Medium Severity

The environment removal confirmation AlertDialog is only rendered when the environment list is not empty. During a discovery refresh in standalone mode, if the environment list temporarily clears, early returns will unmount the dialog even if pendingRemoval is set. This causes the confirmation to vanish mid-flow and potentially reappear for a stale environment.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability to remove stale environments, including new API calls, UI components, and confirmation dialogs. Additionally, two unresolved review comments identify potential bugs in state management (stale data after deletion, dialog disappearing during refresh). New features with open bug findings warrant human review.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow removing stale/offline T3 Connect environments without access to the original machine

2 participants

@soestin@StiensWout
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(web): allow removing stale Connect environments - #4968

Closed
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments
Closed

fix(web): allow removing stale Connect environments#4968
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments

Conversation

@soestin

@soestinsoestin commented Jul 30, 2026

Copy link
Copy Markdown

Problem

T3 Connect environments discovered through the relay only offered Connect. If the original machine was lost or rebuilt, users could not unlink its stale relay record because t3 connect unlink always targets the machine running the command.

Fix

  • add a Remove action to relay-discovered environment rows
  • require destructive confirmation that identifies the environment by label and ID
  • call the existing authenticated relay unlinkEnvironment operation
  • refresh discovery and report success or trace-aware failure
  • cover the direct relay unlink request with a focused test

This stays web-only; desktop inherits the web surface. It does not add a new relay contract or expand the CLI.

Fixes#4965.

Validation

  • vp test run src/cloud/linkEnvironment.test.ts --project unit --passWithNoTests — 10 tests passed
  • pnpm typecheck in apps/web
  • targeted vp lint for the four changed files
  • pnpm build in apps/web

UI evidence

Before — existing connected environment

Before: existing connected environment

After — stale environment can be removed

After: stale environment row with Remove action

Confirmation

Confirmation dialog identifies the environment before unlinking

Generated with GPT-5.6-sol through the T3 Code Codex harness.

Note

Add Remove button to Connect environment list to unlink stale relay environments

  • Adds unlinkRelayEnvironmentFromCloud in linkEnvironment.ts that calls the relay client's unlinkEnvironment method via a DELETE request to /v1/client/environment-links/:environmentId.
  • Adds an unlinkRelayEnvironment atom command in linkEnvironmentAtoms.ts that serializes execution per environmentId.
  • Updates CloudEnvironmentConnectList.tsx to show a destructive 'Remove' button per row; clicking it opens a confirmation dialog, then calls the unlink command, refreshes the list, and shows a success or error toast.

Macroscope summarized 902a37c.


Note

Medium Risk
Changes account-linked environment records via the relay API with destructive UI; scope is web-only and reuses existing unlink contracts rather than new auth paths.

Overview
Users can unlink stale T3 Connect environments from relay discovery when the original machine is gone—without running unlink on that host.

Relay-discovered rows that are not already saved now show Remove next to Connect. Remove opens a confirmation dialog (label + environment ID), then calls the existing authenticated relay unlinkEnvironment path via new unlinkRelayEnvironmentFromCloud and the unlinkRelayEnvironment atom command. On success the list refreshes and a toast confirms; failures surface trace-aware errors. Saved/connected rows still only show the disabled connection state—no Remove there.

A unit test asserts the direct relay DELETE to /v1/client/environment-links/:id with the Clerk bearer token.

Reviewed by Cursor Bugbot for commit 902a37c. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc124ac-bd39-4d4d-874f-1fa9b12afb9d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
@StiensWout

Copy link
Copy Markdown
Contributor

already exists in #4844

@soestin
soestin marked this pull request as ready for review July 30, 2026 11:14
@soestin

Copy link
Copy Markdown
Author

Closing as a duplicate of #4844. Thanks for pointing this out.

@soestinsoestin closed this Jul 30, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:902a37c54d

ℹ️ 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".

setRemovingEnvironmentId(null);
if (result._tag === "Success") {
setPendingRemoval(null);
await refreshRelayEnvironments();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force a post-delete discovery refresh

When Remove is clicked while the initial discovery is still checking environment statuses, this call joins that existing refresh because relayEnvironmentDiscovery.refresh is single-flight. That refresh fetched its environment list before the DELETE, so it completes with the removed record still in state; this is especially likely for an inaccessible environment whose status check takes time. The success toast then appears while the stale row remains until a later manual or lifecycle refresh. Queue a new refresh after the active one, or remove the environment from discovery state after a successful unlink.

Useful? React with 👍 / 👎.

@cursorcursorBot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

</p>
</div>
</div>
{savedConnection ? (

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.

Confirm dialog drops on refresh

Medium Severity

The environment removal confirmation AlertDialog is only rendered when the environment list is not empty. During a discovery refresh in standalone mode, if the environment list temporarily clears, early returns will unmount the dialog even if pendingRemoval is set. This causes the confirmation to vanish mid-flow and potentially reappear for a stale environment.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability to remove stale environments, including new API calls, UI components, and confirmation dialogs. Additionally, two unresolved review comments identify potential bugs in state management (stale data after deletion, dialog disappearing during refresh). New features with open bug findings warrant human review.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow removing stale/offline T3 Connect environments without access to the original machine

2 participants

@soestin@StiensWout
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(web): allow removing stale Connect environments - #4968

Closed
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments
Closed

fix(web): allow removing stale Connect environments#4968
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments

Conversation

@soestin

@soestinsoestin commented Jul 30, 2026

Copy link
Copy Markdown

Problem

T3 Connect environments discovered through the relay only offered Connect. If the original machine was lost or rebuilt, users could not unlink its stale relay record because t3 connect unlink always targets the machine running the command.

Fix

  • add a Remove action to relay-discovered environment rows
  • require destructive confirmation that identifies the environment by label and ID
  • call the existing authenticated relay unlinkEnvironment operation
  • refresh discovery and report success or trace-aware failure
  • cover the direct relay unlink request with a focused test

This stays web-only; desktop inherits the web surface. It does not add a new relay contract or expand the CLI.

Fixes#4965.

Validation

  • vp test run src/cloud/linkEnvironment.test.ts --project unit --passWithNoTests — 10 tests passed
  • pnpm typecheck in apps/web
  • targeted vp lint for the four changed files
  • pnpm build in apps/web

UI evidence

Before — existing connected environment

Before: existing connected environment

After — stale environment can be removed

After: stale environment row with Remove action

Confirmation

Confirmation dialog identifies the environment before unlinking

Generated with GPT-5.6-sol through the T3 Code Codex harness.

Note

Add Remove button to Connect environment list to unlink stale relay environments

  • Adds unlinkRelayEnvironmentFromCloud in linkEnvironment.ts that calls the relay client's unlinkEnvironment method via a DELETE request to /v1/client/environment-links/:environmentId.
  • Adds an unlinkRelayEnvironment atom command in linkEnvironmentAtoms.ts that serializes execution per environmentId.
  • Updates CloudEnvironmentConnectList.tsx to show a destructive 'Remove' button per row; clicking it opens a confirmation dialog, then calls the unlink command, refreshes the list, and shows a success or error toast.

Macroscope summarized 902a37c.


Note

Medium Risk
Changes account-linked environment records via the relay API with destructive UI; scope is web-only and reuses existing unlink contracts rather than new auth paths.

Overview
Users can unlink stale T3 Connect environments from relay discovery when the original machine is gone—without running unlink on that host.

Relay-discovered rows that are not already saved now show Remove next to Connect. Remove opens a confirmation dialog (label + environment ID), then calls the existing authenticated relay unlinkEnvironment path via new unlinkRelayEnvironmentFromCloud and the unlinkRelayEnvironment atom command. On success the list refreshes and a toast confirms; failures surface trace-aware errors. Saved/connected rows still only show the disabled connection state—no Remove there.

A unit test asserts the direct relay DELETE to /v1/client/environment-links/:id with the Clerk bearer token.

Reviewed by Cursor Bugbot for commit 902a37c. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc124ac-bd39-4d4d-874f-1fa9b12afb9d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
@StiensWout

Copy link
Copy Markdown
Contributor

already exists in #4844

@soestin
soestin marked this pull request as ready for review July 30, 2026 11:14
@soestin

Copy link
Copy Markdown
Author

Closing as a duplicate of #4844. Thanks for pointing this out.

@soestinsoestin closed this Jul 30, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:902a37c54d

ℹ️ 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".

setRemovingEnvironmentId(null);
if (result._tag === "Success") {
setPendingRemoval(null);
await refreshRelayEnvironments();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force a post-delete discovery refresh

When Remove is clicked while the initial discovery is still checking environment statuses, this call joins that existing refresh because relayEnvironmentDiscovery.refresh is single-flight. That refresh fetched its environment list before the DELETE, so it completes with the removed record still in state; this is especially likely for an inaccessible environment whose status check takes time. The success toast then appears while the stale row remains until a later manual or lifecycle refresh. Queue a new refresh after the active one, or remove the environment from discovery state after a successful unlink.

Useful? React with 👍 / 👎.

@cursorcursorBot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

</p>
</div>
</div>
{savedConnection ? (

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.

Confirm dialog drops on refresh

Medium Severity

The environment removal confirmation AlertDialog is only rendered when the environment list is not empty. During a discovery refresh in standalone mode, if the environment list temporarily clears, early returns will unmount the dialog even if pendingRemoval is set. This causes the confirmation to vanish mid-flow and potentially reappear for a stale environment.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability to remove stale environments, including new API calls, UI components, and confirmation dialogs. Additionally, two unresolved review comments identify potential bugs in state management (stale data after deletion, dialog disappearing during refresh). New features with open bug findings warrant human review.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow removing stale/offline T3 Connect environments without access to the original machine

2 participants

@soestin@StiensWout
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(web): allow removing stale Connect environments - #4968

Closed
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments
Closed

fix(web): allow removing stale Connect environments#4968
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments

Conversation

@soestin

@soestinsoestin commented Jul 30, 2026

Copy link
Copy Markdown

Problem

T3 Connect environments discovered through the relay only offered Connect. If the original machine was lost or rebuilt, users could not unlink its stale relay record because t3 connect unlink always targets the machine running the command.

Fix

  • add a Remove action to relay-discovered environment rows
  • require destructive confirmation that identifies the environment by label and ID
  • call the existing authenticated relay unlinkEnvironment operation
  • refresh discovery and report success or trace-aware failure
  • cover the direct relay unlink request with a focused test

This stays web-only; desktop inherits the web surface. It does not add a new relay contract or expand the CLI.

Fixes#4965.

Validation

  • vp test run src/cloud/linkEnvironment.test.ts --project unit --passWithNoTests — 10 tests passed
  • pnpm typecheck in apps/web
  • targeted vp lint for the four changed files
  • pnpm build in apps/web

UI evidence

Before — existing connected environment

Before: existing connected environment

After — stale environment can be removed

After: stale environment row with Remove action

Confirmation

Confirmation dialog identifies the environment before unlinking

Generated with GPT-5.6-sol through the T3 Code Codex harness.

Note

Add Remove button to Connect environment list to unlink stale relay environments

  • Adds unlinkRelayEnvironmentFromCloud in linkEnvironment.ts that calls the relay client's unlinkEnvironment method via a DELETE request to /v1/client/environment-links/:environmentId.
  • Adds an unlinkRelayEnvironment atom command in linkEnvironmentAtoms.ts that serializes execution per environmentId.
  • Updates CloudEnvironmentConnectList.tsx to show a destructive 'Remove' button per row; clicking it opens a confirmation dialog, then calls the unlink command, refreshes the list, and shows a success or error toast.

Macroscope summarized 902a37c.


Note

Medium Risk
Changes account-linked environment records via the relay API with destructive UI; scope is web-only and reuses existing unlink contracts rather than new auth paths.

Overview
Users can unlink stale T3 Connect environments from relay discovery when the original machine is gone—without running unlink on that host.

Relay-discovered rows that are not already saved now show Remove next to Connect. Remove opens a confirmation dialog (label + environment ID), then calls the existing authenticated relay unlinkEnvironment path via new unlinkRelayEnvironmentFromCloud and the unlinkRelayEnvironment atom command. On success the list refreshes and a toast confirms; failures surface trace-aware errors. Saved/connected rows still only show the disabled connection state—no Remove there.

A unit test asserts the direct relay DELETE to /v1/client/environment-links/:id with the Clerk bearer token.

Reviewed by Cursor Bugbot for commit 902a37c. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc124ac-bd39-4d4d-874f-1fa9b12afb9d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
@StiensWout

Copy link
Copy Markdown
Contributor

already exists in #4844

@soestin
soestin marked this pull request as ready for review July 30, 2026 11:14
@soestin

Copy link
Copy Markdown
Author

Closing as a duplicate of #4844. Thanks for pointing this out.

@soestinsoestin closed this Jul 30, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:902a37c54d

ℹ️ 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".

setRemovingEnvironmentId(null);
if (result._tag === "Success") {
setPendingRemoval(null);
await refreshRelayEnvironments();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force a post-delete discovery refresh

When Remove is clicked while the initial discovery is still checking environment statuses, this call joins that existing refresh because relayEnvironmentDiscovery.refresh is single-flight. That refresh fetched its environment list before the DELETE, so it completes with the removed record still in state; this is especially likely for an inaccessible environment whose status check takes time. The success toast then appears while the stale row remains until a later manual or lifecycle refresh. Queue a new refresh after the active one, or remove the environment from discovery state after a successful unlink.

Useful? React with 👍 / 👎.

@cursorcursorBot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

</p>
</div>
</div>
{savedConnection ? (

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.

Confirm dialog drops on refresh

Medium Severity

The environment removal confirmation AlertDialog is only rendered when the environment list is not empty. During a discovery refresh in standalone mode, if the environment list temporarily clears, early returns will unmount the dialog even if pendingRemoval is set. This causes the confirmation to vanish mid-flow and potentially reappear for a stale environment.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability to remove stale environments, including new API calls, UI components, and confirmation dialogs. Additionally, two unresolved review comments identify potential bugs in state management (stale data after deletion, dialog disappearing during refresh). New features with open bug findings warrant human review.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow removing stale/offline T3 Connect environments without access to the original machine

2 participants

@soestin@StiensWout
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(web): allow removing stale Connect environments - #4968

Closed
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments
Closed

fix(web): allow removing stale Connect environments#4968
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments

Conversation

@soestin

@soestinsoestin commented Jul 30, 2026

Copy link
Copy Markdown

Problem

T3 Connect environments discovered through the relay only offered Connect. If the original machine was lost or rebuilt, users could not unlink its stale relay record because t3 connect unlink always targets the machine running the command.

Fix

  • add a Remove action to relay-discovered environment rows
  • require destructive confirmation that identifies the environment by label and ID
  • call the existing authenticated relay unlinkEnvironment operation
  • refresh discovery and report success or trace-aware failure
  • cover the direct relay unlink request with a focused test

This stays web-only; desktop inherits the web surface. It does not add a new relay contract or expand the CLI.

Fixes#4965.

Validation

  • vp test run src/cloud/linkEnvironment.test.ts --project unit --passWithNoTests — 10 tests passed
  • pnpm typecheck in apps/web
  • targeted vp lint for the four changed files
  • pnpm build in apps/web

UI evidence

Before — existing connected environment

Before: existing connected environment

After — stale environment can be removed

After: stale environment row with Remove action

Confirmation

Confirmation dialog identifies the environment before unlinking

Generated with GPT-5.6-sol through the T3 Code Codex harness.

Note

Add Remove button to Connect environment list to unlink stale relay environments

  • Adds unlinkRelayEnvironmentFromCloud in linkEnvironment.ts that calls the relay client's unlinkEnvironment method via a DELETE request to /v1/client/environment-links/:environmentId.
  • Adds an unlinkRelayEnvironment atom command in linkEnvironmentAtoms.ts that serializes execution per environmentId.
  • Updates CloudEnvironmentConnectList.tsx to show a destructive 'Remove' button per row; clicking it opens a confirmation dialog, then calls the unlink command, refreshes the list, and shows a success or error toast.

Macroscope summarized 902a37c.


Note

Medium Risk
Changes account-linked environment records via the relay API with destructive UI; scope is web-only and reuses existing unlink contracts rather than new auth paths.

Overview
Users can unlink stale T3 Connect environments from relay discovery when the original machine is gone—without running unlink on that host.

Relay-discovered rows that are not already saved now show Remove next to Connect. Remove opens a confirmation dialog (label + environment ID), then calls the existing authenticated relay unlinkEnvironment path via new unlinkRelayEnvironmentFromCloud and the unlinkRelayEnvironment atom command. On success the list refreshes and a toast confirms; failures surface trace-aware errors. Saved/connected rows still only show the disabled connection state—no Remove there.

A unit test asserts the direct relay DELETE to /v1/client/environment-links/:id with the Clerk bearer token.

Reviewed by Cursor Bugbot for commit 902a37c. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc124ac-bd39-4d4d-874f-1fa9b12afb9d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
@StiensWout

Copy link
Copy Markdown
Contributor

already exists in #4844

@soestin
soestin marked this pull request as ready for review July 30, 2026 11:14
@soestin

Copy link
Copy Markdown
Author

Closing as a duplicate of #4844. Thanks for pointing this out.

@soestinsoestin closed this Jul 30, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:902a37c54d

ℹ️ 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".

setRemovingEnvironmentId(null);
if (result._tag === "Success") {
setPendingRemoval(null);
await refreshRelayEnvironments();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force a post-delete discovery refresh

When Remove is clicked while the initial discovery is still checking environment statuses, this call joins that existing refresh because relayEnvironmentDiscovery.refresh is single-flight. That refresh fetched its environment list before the DELETE, so it completes with the removed record still in state; this is especially likely for an inaccessible environment whose status check takes time. The success toast then appears while the stale row remains until a later manual or lifecycle refresh. Queue a new refresh after the active one, or remove the environment from discovery state after a successful unlink.

Useful? React with 👍 / 👎.

@cursorcursorBot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

</p>
</div>
</div>
{savedConnection ? (

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.

Confirm dialog drops on refresh

Medium Severity

The environment removal confirmation AlertDialog is only rendered when the environment list is not empty. During a discovery refresh in standalone mode, if the environment list temporarily clears, early returns will unmount the dialog even if pendingRemoval is set. This causes the confirmation to vanish mid-flow and potentially reappear for a stale environment.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability to remove stale environments, including new API calls, UI components, and confirmation dialogs. Additionally, two unresolved review comments identify potential bugs in state management (stale data after deletion, dialog disappearing during refresh). New features with open bug findings warrant human review.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow removing stale/offline T3 Connect environments without access to the original machine

2 participants

@soestin@StiensWout
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(web): allow removing stale Connect environments - #4968

Closed
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments
Closed

fix(web): allow removing stale Connect environments#4968
soestin wants to merge 1 commit into
pingdotgg:mainfrom
soestin:agent/remove-stale-connect-environments

Conversation

@soestin

@soestinsoestin commented Jul 30, 2026

Copy link
Copy Markdown

Problem

T3 Connect environments discovered through the relay only offered Connect. If the original machine was lost or rebuilt, users could not unlink its stale relay record because t3 connect unlink always targets the machine running the command.

Fix

  • add a Remove action to relay-discovered environment rows
  • require destructive confirmation that identifies the environment by label and ID
  • call the existing authenticated relay unlinkEnvironment operation
  • refresh discovery and report success or trace-aware failure
  • cover the direct relay unlink request with a focused test

This stays web-only; desktop inherits the web surface. It does not add a new relay contract or expand the CLI.

Fixes#4965.

Validation

  • vp test run src/cloud/linkEnvironment.test.ts --project unit --passWithNoTests — 10 tests passed
  • pnpm typecheck in apps/web
  • targeted vp lint for the four changed files
  • pnpm build in apps/web

UI evidence

Before — existing connected environment

Before: existing connected environment

After — stale environment can be removed

After: stale environment row with Remove action

Confirmation

Confirmation dialog identifies the environment before unlinking

Generated with GPT-5.6-sol through the T3 Code Codex harness.

Note

Add Remove button to Connect environment list to unlink stale relay environments

  • Adds unlinkRelayEnvironmentFromCloud in linkEnvironment.ts that calls the relay client's unlinkEnvironment method via a DELETE request to /v1/client/environment-links/:environmentId.
  • Adds an unlinkRelayEnvironment atom command in linkEnvironmentAtoms.ts that serializes execution per environmentId.
  • Updates CloudEnvironmentConnectList.tsx to show a destructive 'Remove' button per row; clicking it opens a confirmation dialog, then calls the unlink command, refreshes the list, and shows a success or error toast.

Macroscope summarized 902a37c.


Note

Medium Risk
Changes account-linked environment records via the relay API with destructive UI; scope is web-only and reuses existing unlink contracts rather than new auth paths.

Overview
Users can unlink stale T3 Connect environments from relay discovery when the original machine is gone—without running unlink on that host.

Relay-discovered rows that are not already saved now show Remove next to Connect. Remove opens a confirmation dialog (label + environment ID), then calls the existing authenticated relay unlinkEnvironment path via new unlinkRelayEnvironmentFromCloud and the unlinkRelayEnvironment atom command. On success the list refreshes and a toast confirms; failures surface trace-aware errors. Saved/connected rows still only show the disabled connection state—no Remove there.

A unit test asserts the direct relay DELETE to /v1/client/environment-links/:id with the Clerk bearer token.

Reviewed by Cursor Bugbot for commit 902a37c. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc124ac-bd39-4d4d-874f-1fa9b12afb9d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
@StiensWout

Copy link
Copy Markdown
Contributor

already exists in #4844

@soestin
soestin marked this pull request as ready for review July 30, 2026 11:14
@soestin

Copy link
Copy Markdown
Author

Closing as a duplicate of #4844. Thanks for pointing this out.

@soestinsoestin closed this Jul 30, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:902a37c54d

ℹ️ 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".

setRemovingEnvironmentId(null);
if (result._tag === "Success") {
setPendingRemoval(null);
await refreshRelayEnvironments();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force a post-delete discovery refresh

When Remove is clicked while the initial discovery is still checking environment statuses, this call joins that existing refresh because relayEnvironmentDiscovery.refresh is single-flight. That refresh fetched its environment list before the DELETE, so it completes with the removed record still in state; this is especially likely for an inaccessible environment whose status check takes time. The success toast then appears while the stale row remains until a later manual or lifecycle refresh. Queue a new refresh after the active one, or remove the environment from discovery state after a successful unlink.

Useful? React with 👍 / 👎.

@cursorcursorBot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

</p>
</div>
</div>
{savedConnection ? (

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.

Confirm dialog drops on refresh

Medium Severity

The environment removal confirmation AlertDialog is only rendered when the environment list is not empty. During a discovery refresh in standalone mode, if the environment list temporarily clears, early returns will unmount the dialog even if pendingRemoval is set. This causes the confirmation to vanish mid-flow and potentially reappear for a stale environment.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 902a37c. Configure here.

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability to remove stale environments, including new API calls, UI components, and confirmation dialogs. Additionally, two unresolved review comments identify potential bugs in state management (stale data after deletion, dialog disappearing during refresh). New features with open bug findings warrant human review.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow removing stale/offline T3 Connect environments without access to the original machine

2 participants

@soestin@StiensWout