Skip to content

feat(contexts): open clusters in isolated browser tabs - #1619

Open
g-nog wants to merge 2 commits into
skyhook-io:mainfrom
g-nog:feat/isolated-context-tabs
Open

g-nog wants to merge 2 commits into
skyhook-io:mainfrom
g-nog:feat/isolated-context-tabs

Conversation

@g-nog

@g-nog g-nog commented Sep 3, 2026

Copy link
Copy Markdown

Description

Allow standalone local Radar users to open another kubeconfig context in an isolated browser tab without retargeting the current tab.

  • launch a loopback-only sibling Radar process with independent Kubernetes clients, informers, caches, SSE streams, and integration state
  • preserve the exact kubeconfig source and in-file context identity, including direct single-file configurations
  • add an accessible new-tab action to each non-current row in the shared cluster workspace switcher
  • wait for the sibling listener before returning its URL, track child processes, and stop them with the parent
  • surface plain-text API failures instead of replacing them with Unknown error
  • document the standalone-only security and deployment boundaries

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

How has this been tested?

  • Tested locally with minikube/kind
  • Tested against a remote cluster
  • Added/updated unit tests

Validation performed:

  • make build
  • cd web && npm run tsc
  • go test ./internal/server -run 'TestWaitForLocalListener' -count=1
  • real-cluster API and browser smoke test
  • Playwright at 1920x1080 and 1280x800; the per-row action opened a healthy isolated tab with no console errors

The full go test ./... run passes all changed packages but the existing internal/ai TestCursorForceGrantEndToEnd probe times out when run in the concurrent full suite; it passes in isolation. make lint reports existing copylock warnings in internal/server/exec_origin_test.go and internal/server/localterm_disable_test.go because their table cases copy Server values containing vitalsMetricsMemo.

Checklist

  • My code follows the project's coding standards
  • I have performed a self-review of my code
  • I have added comments where necessary
  • My changes generate no new warnings
  • Any dependent changes have been merged

Related issues

None.


Note

Medium Risk
The feature spawns local child processes with kubeconfig credentials and opens new loopback listeners, but it is restricted to unauthenticated standalone mode with same-origin checks on the launch API.

Overview
Standalone local Radar can open another kubeconfig context in a new browser tab without switching the current tab’s cluster. The UI adds a per-row open in new tab action on the cluster switcher when contextTabsEnabled is true.

The backend implements this by POST /api/contexts/{name}/tab, which starts a loopback sibling radar process (own K8s clients, caches, SSE) with CLI flags --context, --context-source, --context-in-file, waits on a readiness file for the bound port, returns a local URL, and tracks/kills child processes on parent shutdown. Explorer gains matching flags plus validation that the three context-ref flags are all-or-nothing; child tabs use RADAR_SETTINGS_PATH for isolated settings.

Capability gating disables context tabs for auth, Cloud, in-cluster, and shared listeners; cluster info exposes contextTabsEnabled. GetContextSource in single-file kubeconfig mode now resolves non-current contexts (with tests). Docs added in docs/context-tabs.md.

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

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Open kubeconfig contexts in isolated browser tabs

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Open non-current kubeconfig contexts in isolated loopback-backed browser tabs.
• Preserve source context identity and manage sibling readiness and shutdown.
• Add accessible switcher controls, error handling, tests, and security documentation.
Diagram

sequenceDiagram
  actor User
  participant Switcher as Context Switcher
  participant Client as Web Client
  participant Parent as Parent Radar
  participant Config as Kubeconfig
  participant Child as Child Radar
  User->>Switcher: Open new tab
  Switcher->>Client: Reserve browser tab
  Client->>Parent: POST context tab
  Parent->>Config: Resolve source context
  Parent->>Child: Start loopback process
  Child-->>Parent: Listener ready
  Parent-->>Client: Return local URL
  Client-->>User: Navigate reserved tab
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. In-process multi-context runtime
  • ➕ Avoids one operating-system process per browser tab
  • ➕ Could support authenticated and shared deployments eventually
  • ➕ Allows centralized lifecycle and resource management
  • ➖ Requires removing singleton assumptions across Kubernetes clients, informers, caches, SSE, and integrations
  • ➖ Introduces substantial context-routing and isolation risk
  • ➖ Has a much larger implementation and regression surface
2. External instance launcher
  • ➕ Keeps process ownership outside the HTTP server
  • ➕ Could provide stronger supervision and restart policies
  • ➖ Requires an additional daemon or platform-specific integration
  • ➖ Complicates standalone installation and communication
  • ➖ Provides a less seamless switcher experience

Recommendation: Use the PR's sibling-process approach for standalone local Radar. It provides strong isolation while preserving existing singleton-based subsystems, and the loopback, authentication, cloud, and shared-listener restrictions bound its security exposure. An in-process multi-context runtime is the stronger long-term architecture for shared deployments, but its scope and isolation risks are disproportionate to this standalone feature.

Files changed (10) +429 / -79

Enhancement (7) +335 / -79
main.goAdd isolated-child context startup flags +5/-0

Add isolated-child context startup flags

• Adds flags carrying the visible context name, source kubeconfig, and original in-file identity into sibling processes. Enables context tabs for the standalone Explorer entrypoint and forwards the preferred startup context.

cmd/explorer/main.go

bootstrap.goPropagate context-tab and startup-context configuration +13/-1

Propagate context-tab and startup-context configuration

• Extends application configuration with an Explorer-only context-tab capability and an explicit preferred context. Initialization prioritizes that context, while server creation forwards the capability flag.

internal/app/bootstrap.go

client.goResolve non-current contexts from direct kubeconfig files +21/-5

Resolve non-current contexts from direct kubeconfig files

• Allows direct single-file mode to resolve any contained context to its source file and original name. File loading occurs outside the client lock, with the historical active-context fallback retained.

internal/k8s/client.go

server.goLaunch and manage isolated context-tab processes +146/-1

Launch and manage isolated context-tab processes

• Adds the context-tab API route, standalone security checks, exact context-source forwarding, loopback port allocation, and readiness polling. Tracks sibling commands, removes exited children, and terminates remaining processes when the parent stops.

internal/server/server.go

ClusterSwitcher.tsxAdd accessible per-context new-tab actions +91/-71

Add accessible per-context new-tab actions

• Extends the shared cluster switcher with an optional secondary action on eligible rows. Restructures each row into separate selection and accessible new-tab buttons while preserving existing context details.

packages/k8s-ui/src/components/cluster-switcher/ClusterSwitcher.tsx

client.tsAdd context-tab API client with robust errors +30/-0

Add context-tab API client with robust errors

• Adds the typed request for launching an isolated context process. Preserves useful plain-text failures while continuing to extract structured JSON error messages when available.

web/src/api/client.ts

ContextSwitcher.tsxOpen isolated contexts through reserved browser tabs +29/-1

Open isolated contexts through reserved browser tabs

• Connects the switcher's new-tab action to the backend API. Reserves a blank tab during the user gesture to avoid popup blocking, detaches its opener, then navigates it or closes it and displays the failure.

web/src/components/ContextSwitcher.tsx

Tests (2) +74 / -0
context_registry_test.goTest direct-mode non-current context resolution +35/-0

Test direct-mode non-current context resolution

• Adds regression coverage proving a non-current context in a directly loaded kubeconfig resolves to the correct file and in-file name.

internal/k8s/context_registry_test.go

context_tabs_test.goTest local listener readiness handling +39/-0

Test local listener readiness handling

• Covers successful listener detection and immediate cancellation of the context-tab readiness wait.

internal/server/context_tabs_test.go

Documentation (1) +20 / -0
context-tabs.mdDocument isolated context tabs and security boundaries +20/-0

Document isolated context tabs and security boundaries

• Explains how standalone users open isolated contexts and which backend state remains independent. Documents loopback-only operation, unsupported deployment modes, and child-process shutdown behavior.

docs/context-tabs.md

@qodo-code-review

qodo-code-review Bot commented Sep 3, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Child loses base path ✓ Resolved 🐞 Bug ≡ Correctness
Description
The response appends the parent's s.basePath, but the child is launched without --base-path and
therefore serves at the root. When Explorer was started with a CLI base path such as /radar, the
returned child URL points to a route the child does not serve.
Code

internal/server/server.go[R4537-4540]

+	args := []string{
+		"--no-browser", "--no-mcp", "--port", strconv.Itoa(port),
+		"--listen-address", "127.0.0.1",
+		"--kubeconfig", source,
Relevance

●●● Strong

The child URL and child routing configuration must agree; omitting the parent's base path is a
deterministic launch bug.

PR-#1082
PR-#1115

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Explorer defines base path as a process-level CLI option with an empty default. The child arguments
omit it, yet the response URL appends the parent's base path; base-path configuration also changes
frontend and API routing.

internal/server/server.go[4537-4544]
internal/server/server.go[4578-4582]
cmd/explorer/main.go[106-109]
internal/server/server.go[1053-1066]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Context-tab children do not inherit the parent's configured base path, while the returned URL assumes they do.

## Issue Context
`--base-path` defaults to empty and is not persisted, so a parent started with a CLI base path launches a child at `/` but returns a URL under the parent's prefix.

## Fix Focus Areas
- internal/server/server.go[4537-4544]
- internal/server/server.go[4578-4582]
- cmd/explorer/main.go[106-109]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Context launch allows CSRF ✓ Resolved 🐞 Bug ⛨ Security
Description
The new unauthenticated loopback endpoint starts child processes without applying the repository's
existing cross-origin guard for process-spawning POST requests. A remote webpage can submit requests
for common context names and repeatedly launch sibling Radar processes, causing local resource
exhaustion.
Code

internal/server/server.go[R4491-4494]

+func (s *Server) handleOpenContextTab(w http.ResponseWriter, r *http.Request) {
+	if !s.contextTabsEnabled() {
+		s.writeError(w, http.StatusNotImplemented, "isolated context tabs are available only in standalone local mode")
+		return
Relevance

●●● Strong

Recent server precedents accept same-origin protection for state-changing or process-affecting
endpoints.

PR-#1081
PR-#1537

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The route starts a process after only feature and context validation. The repository already defines
localOriginOK specifically for state-changing, process-spawning endpoints and applies it to AI
process launches, while global middleware only validates the request Host and configures CORS.

internal/server/server.go[4491-4550]
internal/server/ai_diagnose.go[237-263]
internal/server/listen_address.go[51-70]
internal/server/server.go[420-441]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The context-tab process-spawning endpoint does not validate the request Origin, allowing cross-origin browser requests to trigger child process creation.

## Issue Context
Other state-changing, process-spawning endpoints use `localOriginOK`. Host validation and CORS do not prevent a cross-origin form POST from executing the server-side action.

## Fix Focus Areas
- internal/server/server.go[4491-4495]
- internal/server/ai_diagnose.go[237-255]
- internal/server/context_tabs_test.go[1-39]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Grandchild processes survive shutdown ✓ Resolved 🐞 Bug ☼ Reliability
Description
Every isolated child can launch further context tabs, but Server.Stop kills only the processes
directly tracked by that server. Killing a direct child does not run its shutdown or terminate its
descendants, so nested context-tab processes remain orphaned after the root Explorer exits.
Code

internal/server/server.go[R1201-1205]

+	s.contextTabsMu.Lock()
+	for _, cmd := range s.contextTabProcesses {
+		if cmd.Process != nil {
+			_ = cmd.Process.Kill()
+		}
Relevance

●● Moderate

Process-lifecycle concerns are accepted, but no close precedent specifically establishes recursive
descendant cleanup expectations.

PR-#1081
PR-#873

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Explorer enables ContextTabs for every process. Child launch uses plain exec.Command and each
server tracks only its direct commands; shutdown calls Process.Kill on that direct slice, whereas
the repository's process-group lifecycle support exists only in the AI subsystem.

cmd/explorer/main.go[336-340]
internal/server/server.go[4545-4566]
internal/server/server.go[1198-1208]
internal/ai/process_unix.go[11-18]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Nested context-tab processes survive root shutdown because only directly tracked child PIDs are killed.

## Issue Context
All Explorer invocations enable context tabs, including children. Use platform-appropriate process groups, job objects, or parent-death handling so shutdown terminates the complete spawned tree.

## Fix Focus Areas
- internal/server/server.go[1201-1208]
- internal/server/server.go[4545-4555]
- cmd/explorer/main.go[336-340]
- internal/ai/process_unix.go[11-18]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Released port can be stolen ✓ Resolved 🐞 Bug ☼ Reliability
Description
The handler releases its ephemeral listener before starting the child, creating a close-and-rebind
race. Concurrent tab requests or another local process can claim that port, causing the child to
fail or one request to treat an unrelated listener as ready.
Code

internal/server/server.go[R4526-4529]

+	port := ln.Addr().(*net.TCPAddr).Port
+	if err := ln.Close(); err != nil {
+		s.writeError(w, http.StatusInternalServerError, "could not release the local context-tab port")
+		return
Relevance

●●● Strong

The close-and-rebind race is a concrete reliability defect in ephemeral listener startup and
readiness handling.

PR-#1233
PR-#873

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The parent obtains an ephemeral port, closes the listener, and only later starts the child.
Readiness then checks only whether a TCP connection succeeds, without verifying that the listener
belongs to the spawned process.

internal/server/server.go[4521-4529]
internal/server/server.go[4545-4550]
internal/server/server.go[4568-4598]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The selected child port is unreserved between closing the temporary listener and the child binding it.

## Issue Context
The readiness probe accepts any TCP listener on the selected port, so a competing listener can both prevent startup and be mistaken for the expected child.

## Fix Focus Areas
- internal/server/server.go[4521-4529]
- internal/server/server.go[4545-4550]
- internal/server/server.go[4568-4575]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. 500 responses lack standard logs ✓ Resolved 📘 Rule violation ◔ Observability
Description
Several new 500 response paths either do not log the triggering error or use log messages that do
not match the required [module] Failed to <action> %s/%s: %v structure. This prevents standardized
correlation and diagnosis of context-tab startup failures.
Code

internal/server/server.go[R4521-4524]

+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		s.writeError(w, http.StatusInternalServerError, "could not allocate a local context-tab port")
+		return
Relevance

●●● Strong

The active rule explicitly requires logging errors before 500 responses with standardized
module/action formatting.

PR-#1380
PR-#1101

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 3036628 requires every handler path producing a 500 response to first log the triggering error
using the standardized module/action and %s/%s: %v format. The listener-allocation branch
immediately calls s.writeError, while the readiness branch uses nonconforming log text and
placeholders.

Rule 3036628: Log 500 errors with standardized module/action format before writing the response
internal/server/server.go[4521-4524]
internal/server/server.go[4568-4575]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new context-tab handler returns HTTP 500 for listener allocation, listener release, executable lookup, process startup, and readiness failures without consistently logging the triggering error in the required standardized format before writing the response.

## Issue Context
Each 500 path must log the same error that caused the response, using a literal beginning with `[context-tab] Failed to ` and the required `%s/%s: %v` placeholder structure.

## Fix Focus Areas
- internal/server/server.go[4521-4575]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. openContextTab bypasses apiUrl ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new HTTP call manually concatenates getApiBase() with the endpoint path instead of using the
required shared apiUrl() helper. This bypasses the standardized URL-construction path for new
frontend API calls.
Code

web/src/api/client.ts[6111]

+    `${getApiBase()}/contexts/${encodeURIComponent(name)}/tab`,
Relevance

●●● Strong

The active rule directly requires shared API URL helpers, so bypassing apiUrl is an explicit
compliance violation.

PR-#658
PR-#1082

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 3036564 requires new frontend backend calls to construct HTTP URLs through the
shared API configuration helpers, including apiUrl(). The changed call site instead uses a
template literal containing getApiBase().

Rule 3036564: Use shared API config helpers for all new frontend HTTP/WebSocket calls
web/src/api/client.ts[6109-6113]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new `openContextTab` request manually concatenates `getApiBase()` and its endpoint path instead of using the shared `apiUrl()` helper.

## Issue Context
`apiUrl` is already imported by this module and is the required URL-construction helper for new frontend backend calls.

## Fix Focus Areas
- web/src/api/client.ts[6109-6113]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (5)
7. Unsupported deployments show action ✓ Resolved 🐞 Bug ≡ Correctness
Description
ContextSwitcher always supplies the new-tab callback, so authenticated, Cloud, and other
unsupported deployments render an action that the backend always rejects with 501. Clicking it opens
and then closes a blank popup before displaying an error instead of hiding the unavailable feature.
Code

web/src/components/ContextSwitcher.tsx[R236-239]

+        onOpenInNewTab={item => {
+          const parsed = parsedById.get(item.id)
+          if (parsed) void handleOpenTab(parsed)
+        }}
Relevance

●●● Strong

Accepted history favors fixing UI affordances that expose unsupported backend actions; PR explicitly
limits tabs to standalone mode.

PR-#1478
PR-#542

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The callback is supplied unconditionally and the shared component renders its button whenever that
callback exists. The backend independently rejects authenticated, in-cluster, Cloud, and
shared-listener configurations.

web/src/components/ContextSwitcher.tsx[219-239]
packages/k8s-ui/src/components/cluster-switcher/ClusterSwitcher.tsx[424-436]
internal/server/server.go[4491-4495]
internal/server/server.go[4608-4610]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The UI renders the context-tab action even when the backend configuration cannot support it.

## Issue Context
Expose the backend's effective context-tabs capability and only provide `onOpenInNewTab` when that capability is true; deployment mode alone does not cover authentication or shared listeners.

## Fix Focus Areas
- web/src/components/ContextSwitcher.tsx[219-239]
- packages/k8s-ui/src/components/cluster-switcher/ClusterSwitcher.tsx[424-436]
- internal/server/server.go[4608-4610]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Shutdown can miss new child ✓ Resolved 🐞 Bug ☼ Reliability
Description
handleOpenContextTab starts a process before taking contextTabsMu, while Stop clears the
tracked slice without recording that shutdown has begun. A launch racing shutdown can append its
child after Stop has finished killing the existing entries, allowing that process to outlive the
server.
Code

internal/server/server.go[R4553-4555]

+	s.contextTabsMu.Lock()
+	s.contextTabProcesses = append(s.contextTabProcesses, cmd)
+	s.contextTabsMu.Unlock()
Relevance

●●● Strong

The launch-registration race can leave processes alive after shutdown; recent server concurrency
findings are accepted.

PR-#1115
PR-#972

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Process startup occurs outside the process-list mutex, and registration follows afterward. Stop
kills the current list and resets it to nil but does not set a state that subsequent launch
registration checks.

internal/server/server.go[1198-1208]
internal/server/server.go[4545-4555]
cmd/explorer/main.go[552-567]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A context-tab process can start and register after server shutdown has already cleared the process list.

## Issue Context
Introduce a stopped/closing state under the same mutex and reject or immediately kill children that start after shutdown begins.

## Fix Focus Areas
- internal/server/server.go[1198-1208]
- internal/server/server.go[4545-4555]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Comment records historical behavior ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The added comment describes the fallback in terms of preserving historical behavior rather than
documenting only its current invariant. This introduces explicit implementation-history commentary
prohibited by the checklist.
Code

internal/k8s/client.go[R2178-2179]

+		// Preserve the historical current-context fallback when the source
+		// cannot be reread; startup already validated this binding.
Relevance

●●● Strong

The rule explicitly prohibits implementation-history comments, making this a straightforward
maintainability fix.

PR-#1138
PR-#873

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 3036538 disallows code comments containing explicit change or implementation history. The newly
added phrase Preserve the historical current-context fallback directly characterizes the behavior
by its history.

Rule 3036538: Disallow references to tickets or PR history in code comments
internal/k8s/client.go[2178-2179]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The comment refers to preserving a `historical` fallback, embedding change history in the source.

## Issue Context
Retain the useful invariant that startup validated the binding, but phrase the comment entirely in terms of current behavior and rationale.

## Fix Focus Areas
- internal/k8s/client.go[2178-2179]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Incomplete context silently ignored ✓ Resolved 🐞 Bug ≡ Correctness
Description
The three new CLI flags are accepted independently, but any reference missing either source or
in-file name is treated as empty and silently falls back to the kubeconfig's current context.
Invoking Explorer with --context alone can therefore connect to a different cluster than the
command requests.
Code

cmd/explorer/main.go[R101-103]

+	contextName := flag.String("context", "", "Initial kubeconfig context (used for isolated browser tabs)")
+	contextSource := flag.String("context-source", "", "Source kubeconfig file for --context (used for isolated browser tabs)")
+	contextInFile := flag.String("context-in-file", "", "Original context name inside --context-source (used for isolated browser tabs)")
Relevance

●●● Strong

Accepted findings consistently require validation for configuration inputs; incomplete context
binding risks unintended startup behavior.

PR-#732
PR-#1082

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Main constructs the reference without validating flag combinations. ContextRef.Empty returns true
whenever source or in-file name is absent, and initialization then falls back to normal startup
context selection.

cmd/explorer/main.go[101-103]
cmd/explorer/main.go[336-340]
internal/k8s/context_source.go[21-33]
internal/app/bootstrap.go[127-136]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Partial isolated-context CLI references are silently ignored and can start Explorer on the wrong cluster.

## Issue Context
Require all three context flags together, or reject partial combinations before Kubernetes initialization.

## Fix Focus Areas
- cmd/explorer/main.go[101-103]
- cmd/explorer/main.go[336-340]
- internal/k8s/context_source.go[21-33]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Child races shared settings writes ✓ Resolved 🐞 Bug ☼ Reliability
Description
The separately launched child reloads namespace defaults and may perform a load-modify-save against
the same settings.json as the parent. Because settings synchronization is process-local and both
processes use the same temporary filename, concurrent child startup and parent settings updates can
lose unrelated settings or fail a rename.
Code

internal/server/server.go[R4537-4540]

+	args := []string{
+		"--no-browser", "--no-mcp", "--port", strconv.Itoa(port),
+		"--listen-address", "127.0.0.1",
+		"--kubeconfig", source,
Relevance

●● Moderate

Cross-process settings races are plausible, but historical evidence does not clearly establish this
feature's required isolation model.

PR-#972
PR-#1115

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The child is a separate executable and receives no isolated settings path or namespace override.
Startup seeds namespace preferences when a configured namespace exists, while settings update
protection is only an in-process mutex and every process writes through the same .tmp path before
rename.

internal/server/server.go[4537-4544]
internal/app/bootstrap.go[201-222]
internal/settings/settings.go[120-151]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Context-tab children can concurrently rewrite the parent's shared settings file without cross-process synchronization.

## Issue Context
Prevent isolated children from seeding shared namespace settings, provide a process-specific settings path, or add a cross-process lock and collision-free atomic temporary files.

## Fix Focus Areas
- internal/server/server.go[4537-4544]
- internal/app/bootstrap.go[201-222]
- internal/settings/settings.go[120-151]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 41 rules
Review mode: ⚖️ Balanced

Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread web/src/api/client.ts Outdated
Comment thread internal/server/server.go Outdated
Comment thread internal/k8s/client.go Outdated
Comment thread internal/server/server.go
Comment thread internal/server/server.go
Comment thread internal/server/server.go Outdated
Comment thread internal/server/server.go
Comment thread web/src/components/ContextSwitcher.tsx Outdated
Comment thread cmd/explorer/main.go
Comment thread internal/server/server.go

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes using default effort and found 4 potential issues.

Fix All in Cursor

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

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 202e813. Configure here.

Comment thread internal/server/server.go
Comment thread web/src/components/ContextSwitcher.tsx Outdated
Comment thread internal/server/server.go Outdated
Comment thread internal/k8s/client.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant