Skip to content

fix(mobile): removing a saved environment from the trash button never silently no-ops - #18228

Open
fixfon wants to merge 1 commit into
pingdotgg:mainfrom
fixfon:fix/ios-remove-environment
Open

fixfon wants to merge 1 commit into
pingdotgg:mainfrom
fixfon:fix/ios-remove-environment

Conversation

@fixfon

@fixfon fixfon commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Problem

Refs #12012 (maintainer triage).

The trash on a saved direct environment row calls onRemoveEnvironmentPress, which in two cases gave the user no feedback at all:

  1. If the environment was not found in connectedEnvironments, the handler hit a bare return before Alert.alert, so the tap was silently dropped.
  2. On confirm, it did void controller.removeEnvironment(id) and discarded the result. A failed removal (for example a failed SecureStore write) only reached console.warn, so "Remove" looked identical to a tap that did nothing, and the row stayed.

Fix

apps/mobile only. The decision logic moved out of the hook into presentRemoveEnvironmentConfirm (remove-environment-confirm.ts):

  • The confirm is always presented. An environment missing from the connected list is labelled by its id instead of dropping the tap. Copy and the T3 Connect "Open T3 Account" variant are unchanged.
  • The removal result is no longer discarded. A failure shows "Could not remove environment" with the error message; interrupts stay quiet.

Tests (vp test run src/state/remove-environment-confirm.test.ts, 4 passing): missing environment still confirms and removes by id, relay copy, failed removal is reported, successful removal stays quiet. tsc --noEmit for apps/mobile, lint and format on the touched files are clean.

What I could and could not reproduce (iOS simulator only)

Unmodified main (18656a3), iPhone 17 Pro iOS 26.3 and iPhone 16 Pro iOS 18.3, isolated backend in the worktree .t3, Settings → Environments → row → trash:

  • Natural flow works on current main. For a connected row and for an offline row, the native confirm does appear inside the Settings form sheet, Remove removes the row, and it is still gone after an app relaunch. So I could not reproduce the "confirm is presented but invisible behind the form sheet" theory from the triage, and I did not change how the confirm is presented. 26.3 connected, 26.3 offline, 18.3, removed + relaunch recording.
  • Neither silent-drop state is reachable through the UI on this commit. The row list and the handler read the same connectedEnvironments array, and I could not make a removal fail for real. I forced each state with a temporary, uncommitted local patch (a find predicate that never matches; a removeEnvironment that returns a failure), applied identically to BEFORE and AFTER, each run from a fresh app launch. These show the code path, not the original reporter's failure.
Forced state Before (unmodified handler) After (this PR)
Lookup miss Tap on trash does nothing (screenshot, recording) Confirm appears labelled with the environment id (screenshot); Remove removes it (screenshot); still gone after relaunch (screenshot, recording)
Removal fails Confirm, Remove, nothing visible, row stays (screenshot, recording) "Could not remove environment" alert, row stays (screenshot, recording)
Natural, no forcing (regression check) See above Offline direct row: trash, confirm, Remove, row gone, still gone after relaunch (recording)

All evidence files are in this gist, not in the repository.

Not checked, and not done

  • Android (no device or emulator on this machine).
  • A physical iPhone and the 2026-09-15 App Store binary. That build predates the current Environments detail screen, so the reported failure may come from the older UI, which I could not run.
  • Keychain persistence across delete and reinstall. I only checked persistence across an app relaunch.
  • The triage's in-tree confirm (showConfirmDialog) and the "Forget saved environments" escape hatch in Client Storage. I left the native Alert.alert because it renders correctly in the form sheet on both iOS versions above, and the escape hatch is a separate feature.
  • Local build note: this machine's Xcode 27.0 SDK lacks the iOS 27.1 APIs that T3LayoutMetricsView.swift guards with #if compiler(>=6.4). I disabled those blocks locally to build the dev client and did not commit that.

Prior attempt

#12730 was closed by its author with no maintainer closure comment, so I looked at its review feedback. It asked for a removal entry point for a saved environment missing from the connected list. This PR makes the existing trash always respond for such a row, but this commit has no UI that lists a saved environment outside connectedEnvironments, so I added no new entry point.


Model and harness: Claude Sonnet 5.5 via Claude Code in T3 Code.

🤖 Generated with Claude Code

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Oct 11, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 11, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at d02f304

Macroscope's review found this PR approvable — This is a localized mobile bug fix that makes stale environment removal actionable and surfaces failed removals without changing the normal confirmation flow. The new behavior is directly tested and has no broader schema, infrastructure, security, or default-setting impact.

Notes:

  • Diff unchanged. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 11, 2026 — with ChatGPT Codex Connector
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 11, 2026 13:59

Dismissing prior approval to re-evaluate d02f304

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 9b1c87a9-de6b-43d3-a0ee-f8fb80af03d7
📥 Commits

Reviewing files that changed from the base of the PR and between ed0f7b9 and d02f304.

📒 Files selected for processing (3)
  • apps/mobile/src/state/remove-environment-confirm.test.ts
  • apps/mobile/src/state/remove-environment-confirm.ts
  • apps/mobile/src/state/use-remote-environment-registry.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

The change adds a shared environment-removal confirmation helper and uses it in remote environment management. The helper handles missing environment details, relay-managed prompts, removal results, and failure alerts.

Changes: Environment removal confirmation

Layer / File(s) Summary
Confirmation and removal behavior
apps/mobile/src/state/remove-environment-confirm.ts, apps/mobile/src/state/remove-environment-confirm.test.ts
The helper selects the trimmed environment label or falls back to its ID. It presents different prompts for relay-managed and other environments, and reports failed removal results. Tests cover missing environment details, relay-managed messaging, and removal outcomes.
Remote registry integration
apps/mobile/src/state/use-remote-environment-registry.ts
Remote environment management delegates confirmation to the helper and passes the selected environment, removal callback, account navigation callback, and alert function.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant useRemoteConnections
  participant presentRemoveEnvironmentConfirm
  participant Alert
  participant remove
  useRemoteConnections->>presentRemoveEnvironmentConfirm: Pass environment and callbacks
  presentRemoveEnvironmentConfirm->>Alert: Show confirmation
  Alert->>presentRemoveEnvironmentConfirm: Invoke removal action
  presentRemoveEnvironmentConfirm->>remove: Remove environment by ID
  remove-->>presentRemoveEnvironmentConfirm: Return removal result
  presentRemoveEnvironmentConfirm->>Alert: Report failure when removal fails
Loading
Merge Risk: ⚪ Minimal · up to d02f3

No actionable issue remains from this review; the change is mergeable after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to d02f3

The change remains limited to device-local environment removal and preserves confirmation and existing deletion controls. No introduced security issue was established, but complete cleanup and recovery guarantees were not verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The examined deletion path remains scoped to a selected environment in the device registry and its dependent local state. No expansion into account deregistration or remote host deletion was established.

Trust Boundaries and Controls

  • observed — Missing presentation metadata no longer blocks confirmation, but removal still checks the authoritative registry entry and rejects platform-managed environments. Labels and summary flags do not substitute another ID or grant additional cleanup authority.

Resilience and Maintainability Implications

  • observed — The production command wrapper converts rejected execution into settled failure results. The new helper reports non-interrupt failures and retains the existing convention of keeping interrupt-only outcomes quiet; it adds no rollback or recovery mechanism.
Pre-merge checks | Passed 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check Passed The title clearly describes the primary fix: preventing saved-environment removal from silently doing nothing. It is concise, specific, and uses the repository’s conventional commit format.
Description check Passed The description is complete and directly addresses the problem, implemented change, issue reference, verification results, UI evidence, limitations, and agent disclosure. The "Fix" heading replaces th…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

… silently no-ops

The trash handler returned without feedback when the environment was missing
from the connected list, and discarded the result of the removal, so a failed
remove looked identical to a tap that did nothing. Always present the confirm
(labelled by environment id when the summary is unknown) and report a failed
removal.

Refs pingdotgg#12012

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@fixfon
fixfon force-pushed the fix/ios-remove-environment branch from d02f304 to a9cdf03 Compare October 14, 2026 08:21

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

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants