feat(f11): add native macOS fleet desktop - #167
Conversation
Package the existing local fleet IDE in a Wails v2 macOS shell with a native, path-private kubeconfig-folder import flow. Preserve the hardened in-process UI boundary and atomic session handoff. GSTACK-Checkpoint: 2026-07-14/f11-native-desktop-shell#1 Signed-off-by: Gnani Rahul <gnani.nutakki@gmail.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds a native macOS Wails desktop shell for the existing local fleet IDE, with in-process web UI serving, native kubeconfig directory import, atomic session replacement, macOS arm64 build/signing automation, CLI wiring, tests, and architecture documentation. ChangesNative desktop shell
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant Wails
participant DesktopBridge
participant desktopHost
participant WebUI
User->>Wails: Open native desktop application
Wails->>WebUI: Serve wails://wails through in-process middleware
WebUI->>DesktopBridge: Choose kubeconfig directory
DesktopBridge->>desktopHost: Import selected directory
desktopHost->>desktopHost: Create and atomically swap session
desktopHost-->>WebUI: Return import success
WebUI->>WebUI: Reload application
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (4)
Makefile (1)
47-53: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winVerify the produced executable is actually ARM64.
The target requests
darwin/arm64, but the post-build checks only the bundle path, identifier, and signature. Add an architecture assertion so an incorrectly produced artifact cannot pass the packaging gate. Wails listsdarwin/arm64as a supported target. (wails.io)Proposed validation
app='cmd/sith-desktop/build/bin/Sith.app'; \ test -d "$$app"; \ + test "$$(lipo -archs "$$app/Contents/MacOS/Sith")" = arm64; \ "$(PLISTBUDDY)" -c 'Set :CFBundleIdentifier com.ardurai.sith' "$$app/Contents/Info.plist"; \🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Makefile` around lines 47 - 53, Update the post-build validation in the Makefile target to assert that the generated Sith.app executable is ARM64, in addition to the existing bundle, identifier, and signature checks. Inspect the executable inside the app bundle using the available architecture inspection command and fail the target unless it reports arm64.internal/webui/desktop.go (1)
29-45: 🩺 Stability & Availability | 🔵 Trivial | ⚖️ Poor tradeoffUnbounded blocking: a hung in-flight request stalls
Replaceand, transitively, all new requests.
ServeHTTPholds the read lock for the full duration of the downstreamServeHTTPcall. Go'ssync.RWMutexgives waiting writers priority, so onceReplacestarts waiting onLock(), every subsequentRLock()(i.e. every new incoming request) also blocks until the stuck request finishes. There's no timeout anywhere in this path, so a single hung fleet-engine call can freeze the whole desktop session until the process is restarted.Consider bounding the in-flight request (e.g. request context deadline) or documenting that downstream handlers must guarantee bounded execution time.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/webui/desktop.go` around lines 29 - 45, Update InProcessHandler.ServeHTTP and Replace so a hung downstream LocalHandler.ServeHTTP cannot hold the RWMutex indefinitely; bound in-flight request execution with an appropriate request-context deadline or timeout while preserving atomic handler replacement and fail-closed behavior for a nil current handler.internal/cli/desktop.go (1)
50-71: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winHydrator failures are silently discarded.
_ = hydrator.Run(ctx)swallows any error from the hydration loop with no logging path. Since no logger is threaded throughdesktopSession/desktopHost, a persistent hydration failure (e.g., repeated cluster read errors) would leave the desktop UI silently stale with zero way to diagnose it.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/cli/desktop.go` around lines 50 - 71, The goroutine in newDesktopSession discards errors from hydrator.Run, leaving persistent hydration failures undiagnosed. Add an error-reporting path through the desktopSession/desktopHost lifecycle and use it when the hydration goroutine returns an error, preserving cancellation and cleanup behavior while ensuring failures are logged or surfaced.internal/cli/desktop_darwin.go (1)
50-85: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winSignal-derived
ctxfromExecuteDesktopis never wired to app shutdown.
ExecuteDesktop(desktop_execute.go) buildsctxviasignal.NotifyContext(..., os.Interrupt)and passes it here, butrunDesktoponly uses it to constructdesktopHost/sessions — it never watchesctx.Done()to callruntime.Quitor otherwise stopwails.Run. On SIGINT (relevant forgo run, dev builds, or any CI/E2E harness that terminates the process), the session's hydrator/context is cancelled while the window keeps running andwails.Runkeeps blocking, leaving a stale, half-torn-down UI instead of a clean exit.♻️ Suggested fix: watch ctx and quit gracefully
bridge := &DesktopBridge{host: host} + go func() { + <-ctx.Done() + if bridge.ctx != nil { + runtime.Quit(bridge.ctx) + } + }() err = wails.Run(&options.App{🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/cli/desktop_darwin.go` around lines 50 - 85, Update runDesktop to watch ctx.Done() while wails.Run is active and request a graceful Wails application shutdown via the appropriate runtime quit mechanism. Ensure the watcher is stopped or exits when the app shuts down, and preserve the existing host.Close cleanup and wails.Run error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cmd/sith-desktop/wails.json`:
- Around line 5-6: Update the Wails configuration in wails.json so
frontend:build no longer runs against a missing default frontend directory:
either add the required frontend directory under cmd/sith-desktop or set
frontend:dir to the actual existing frontend location, while preserving the
intended build command.
In `@internal/cli/desktop.go`:
- Around line 25-40: Update the RunE validation in newDesktopCommand so a nil
reader or local client is allowed when options.kubeconfigDir is set, letting
runDesktop apply the supplied kubeconfig override. Retain the existing error for
invocations lacking both default dependencies and a kubeconfig directory, and
continue passing the resolved options to runDesktop.
In `@Makefile`:
- Around line 44-46: Update the Wails validation in desktop-build to require the
pinned v2.12.0 CLI version, and add the -nomodsync flag to the Wails build
invocation so it does not rewrite go.mod. Keep the existing command availability
check and build options unchanged.
In `@README.md`:
- Around line 364-369: Update the native import bridge documentation to
consistently describe all three outcomes: success, cancellation, and
sanitized/redacted errors, while preserving the guarantee that no absolute path
or kubeconfig content is exposed. Apply this wording in README.md lines 364-369,
docs/adr/0010-native-local-desktop-shell.md lines 22-24, and
sessions/2026-07-14-f11-native-desktop-shell.md lines 21-23.
---
Nitpick comments:
In `@internal/cli/desktop_darwin.go`:
- Around line 50-85: Update runDesktop to watch ctx.Done() while wails.Run is
active and request a graceful Wails application shutdown via the appropriate
runtime quit mechanism. Ensure the watcher is stopped or exits when the app
shuts down, and preserve the existing host.Close cleanup and wails.Run error
handling.
In `@internal/cli/desktop.go`:
- Around line 50-71: The goroutine in newDesktopSession discards errors from
hydrator.Run, leaving persistent hydration failures undiagnosed. Add an
error-reporting path through the desktopSession/desktopHost lifecycle and use it
when the hydration goroutine returns an error, preserving cancellation and
cleanup behavior while ensuring failures are logged or surfaced.
In `@internal/webui/desktop.go`:
- Around line 29-45: Update InProcessHandler.ServeHTTP and Replace so a hung
downstream LocalHandler.ServeHTTP cannot hold the RWMutex indefinitely; bound
in-flight request execution with an appropriate request-context deadline or
timeout while preserving atomic handler replacement and fail-closed behavior for
a nil current handler.
In `@Makefile`:
- Around line 47-53: Update the post-build validation in the Makefile target to
assert that the generated Sith.app executable is ARM64, in addition to the
existing bundle, identifier, and signature checks. Inspect the executable inside
the app bundle using the available architecture inspection command and fail the
target unless it reports arm64.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 602180f1-8170-4c27-b7aa-030676bb3531
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (22)
.gitignoreMakefileREADME.mdcmd/sith-desktop/main.gocmd/sith-desktop/wails.jsondocs/adr/0010-native-local-desktop-shell.mddocs/adr/README.mdgo.modinternal/cli/desktop.gointernal/cli/desktop_darwin.gointernal/cli/desktop_execute.gointernal/cli/desktop_other.gointernal/cli/desktop_test.gointernal/cli/root.gointernal/privacy/boundary_test.gointernal/webui/assets/app.jsinternal/webui/assets/index.htmlinternal/webui/desktop.gointernal/webui/desktop_test.gointernal/webui/server.gointernal/webui/server_test.gosessions/2026-07-14-f11-native-desktop-shell.md
Use non-blocking session leases, a sanitized hydration-stop state, directory-only startup, graceful signal shutdown, and reproducible pinned Wails packaging with ARM64 verification. GSTACK-Checkpoint: 2026-07-14/f11-native-desktop-shell#2 Signed-off-by: Gnani Rahul <gnani.nutakki@gmail.com>
|
Addressed the CodeRabbit review in b99820e:
@coderabbitai review |
|
✅ Action performedReview finished.
|
Signed-off-by: Gnani Rahul <gnani.nutakki@gmail.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
internal/cli/desktop.go (1)
177-189: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winWait for the drained channel before closing the session
Close()drops the channel returned byhost.handler.Replace(nil)and callssession.close()immediately; that can tear downwebui.Applicationwhile a request leased to the old session is still in flight.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/cli/desktop.go` around lines 177 - 189, Update desktopHost.Close to retain the channel returned by host.handler.Replace(nil) and wait for it to drain before calling session.close(). Preserve the existing mutex, closed-state guard, session detachment, and nil-handler replacement behavior, ensuring the webui.Application session is closed only after in-flight requests complete.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@internal/cli/desktop.go`:
- Around line 177-189: Update desktopHost.Close to retain the channel returned
by host.handler.Replace(nil) and wait for it to drain before calling
session.close(). Preserve the existing mutex, closed-state guard, session
detachment, and nil-handler replacement behavior, ensuring the webui.Application
session is closed only after in-flight requests complete.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: d237e84e-c85c-4265-bef3-860a25ef10cb
📒 Files selected for processing (13)
MakefileREADME.mdcmd/sith-desktop/frontend/.gitkeepcmd/sith-desktop/wails.jsondocs/adr/0010-native-local-desktop-shell.mdinternal/cli/desktop.gointernal/cli/desktop_darwin.gointernal/cli/desktop_test.gointernal/webui/assets/app.jsinternal/webui/desktop.gointernal/webui/desktop_test.gointernal/webui/server_test.gosessions/2026-07-14-f11-native-desktop-shell.md
🚧 Files skipped from review as they are similar to previous changes (7)
- cmd/sith-desktop/wails.json
- docs/adr/0010-native-local-desktop-shell.md
- internal/webui/assets/app.js
- internal/cli/desktop_darwin.go
- Makefile
- README.md
- internal/webui/server_test.go
What changed
sith desktop, a native macOS Wails v2 shell around the existing local fleet IDE.wails://wailswith no TCP listener, no telemetry, and no second Kubernetes client.Review and safety
com.ardurai.sithidentifier and ad-hoc signature. Developer ID signing, notarization, stapling, and public-release provenance remain E9 follow-up work.Validation
make cimake e2e-isolation(PostgreSQL RLS plus 50,000-case selector fuzz)make release-checkKIND=/Volumes/EXTENDED/MacData/tools/bin/kind make e2e-kind(PASS, 158.742s)make desktop-build WAILS=/Volumes/EXTENDED/MacData/go/bin/wailsCloses #166.
Summary by CodeRabbit
sith desktopcommand for running the local fleet IDE in a native macOS window.make desktop-build, including bundle preparation and signing for local verification.