Skip to content

feat(desktop): add required update mechanism#552

Merged
saddlepaddle merged 1 commit intomainfrom
smiling-spider-85c6c8
Dec 30, 2025
Merged

feat(desktop): add required update mechanism#552
saddlepaddle merged 1 commit intomainfrom
smiling-spider-85c6c8

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Dec 30, 2025

Summary

  • Add mechanism to force desktop users to update when breaking changes are deployed (e.g., auth system changes)
  • Users on outdated versions see a blocking page instead of the app
  • Integrates with existing auto-updater system

Changes

API:

  • GET /api/desktop/version - Returns { minimumVersion, message? }

Desktop:

  • useVersionCheck hook - Fetches and compares versions, re-checks on network reconnect
  • UpdateRequiredPage component - Blocking UI with update button
  • Version gate added before auth in MainScreen
  • window.App.appVersion exposed via preload
  • check mutation added to auto-update tRPC router

Behavior

Scenario Result
Version OK Normal app
Version outdated Blocking page
Offline / API down Fail open (allow in)
Network reconnects Re-check if not verified

How to Force Update

Update MINIMUM_DESKTOP_VERSION in apps/api/src/app/api/desktop/version/route.ts

Test plan

  • Version check passes when current >= minimum
  • Version check blocks when current < minimum
  • App works when API is unreachable (fail open)
  • Re-checks when network comes back online
  • "Check for Update" triggers auto-updater
  • "Download Manually" opens releases page

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Desktop app enforces a minimum required version via a remote endpoint.
    • New "Update Required" screen guides blocked users to check, download, or install updates.
    • App exposes its current version to the UI so version comparisons are accurate.
    • Added a version-check hook and UI flow; users can trigger immediate update checks.
  • Telemetry
    • Desktop version now included in analytics and feature-flag identification.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

Adds a backend endpoint returning minimum desktop version, injects build-time app version into the preload API, exposes that version to renderer, adds a hook to fetch/compare versions, a UI to require updates, integrates the check into the main screen, and adds a TRPC mutation to trigger update checks.

Changes

Cohort / File(s) Summary
Backend API Endpoint
apps/api/src/app/api/desktop/version/route.ts
New GET endpoint returns JSON { minimumVersion: "0.0.39", /* optional message */ }.
Build config & Preload API
apps/desktop/electron.vite.config.ts
apps/desktop/src/preload/index.ts
Import version from package.json and expose it via __APP_VERSION__ define; preload declares __APP_VERSION__ and adds appVersion to window.App.
Auto-update TRPC
apps/desktop/src/lib/trpc/routers/auto-update/index.ts
Adds public check mutation that calls checkForUpdates() from main auto-updater.
Version check hook
apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
New useVersionCheck hook fetches /api/desktop/version (via NEXT_PUBLIC_API_URL), compares window.App.appVersion with minimumVersion using semver, exposes loading/blocked/error state, fail-open on network errors, and re-checks on online events.
Update UI & integration
apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
apps/desktop/src/renderer/screens/main/index.tsx
New UpdateRequiredPage component (check/install/manual download flows, subscribes to auto-update events). Main screen uses useVersionCheck to show loading or render UpdateRequiredPage when blocked.
Renderer analytics & identifier
apps/desktop/src/main/lib/analytics/index.ts
apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
Append desktop_version (from app.getVersion() in main and window.App.appVersion in renderer) to analytics identify/track calls.
Dependencies
apps/desktop/package.json
Adds runtime dependency semver@^7.7.3 for version comparisons.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DesktopApp as Desktop App (Renderer)
    participant Preload as Preload API (window.App)
    participant Hook as useVersionCheck
    participant Backend as Backend API
    participant TRPC as TRPC Auto-updater
    participant AutoUpdater as Main Auto-updater
    participant UpdateUI as UpdateRequiredPage

    User->>DesktopApp: Launch
    DesktopApp->>Hook: mount/useVersionCheck()
    Hook->>Preload: read appVersion
    Preload-->>Hook: return __APP_VERSION__
    Hook->>Backend: GET /api/desktop/version
    Backend-->>Hook: { minimumVersion, message? }
    Hook->>Hook: compare(current, minimum) [semver]
    alt current < minimum
        Hook-->>DesktopApp: isBlocked = true, requirements
        DesktopApp->>UpdateUI: render with props
        User->>UpdateUI: "Check for Updates"
        UpdateUI->>TRPC: mutation check()
        TRPC->>AutoUpdater: invoke checkForUpdates()
        AutoUpdater-->>TRPC: update status events (subscribe)
        TRPC-->>UpdateUI: progress/status via subscription
        UpdateUI->>User: show progress / install / manual link
    else current >= minimum
        Hook-->>DesktopApp: isBlocked = false
        DesktopApp->>User: proceed to normal app
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I checked the versions, snug and spry,
I nudged the app to look up high.
"Fetch, install, or link to go!" I sing—
A hop, a patch, a happy ping.
Now desktops bounce and updates fly.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main feature addition: a required update mechanism for the desktop app.
Description check ✅ Passed The description includes a summary, detailed changes across API and desktop, behavior matrix, update instructions, and test plan, covering all major template sections comprehensively.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e39477 and 0a70717.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • apps/api/src/app/api/desktop/version/route.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/package.json
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/main/lib/analytics/index.ts
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/api/src/app/api/desktop/version/route.ts
🧰 Additional context used
📓 Path-based instructions (5)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/main/lib/analytics/index.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use type safety and avoid any types unless absolutely necessary in TypeScript files

Files:

  • apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/main/lib/analytics/index.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
apps/**/src/**/**/[A-Z]*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Structure component folders with one component per file using format ComponentName/ComponentName.tsx with index.ts barrel export

Files:

  • apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
apps/desktop/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Move Node.js functionality needed in Electron renderer to src/main/lib/ and communicate via IPC

Files:

  • apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/main/lib/analytics/index.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
apps/desktop/src/{shared/ipc-channels.ts,main/**/*ipcs.ts,renderer/**/*.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Define all Electron IPC channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers

Files:

  • apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
  • apps/desktop/src/renderer/screens/main/index.tsx
🧠 Learnings (7)
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables in `src/main/index.ts` with `override: true` before any other imports in the desktop app

Applied to files:

  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/main/lib/analytics/index.ts
  • apps/desktop/electron.vite.config.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/{shared/ipc-channels.ts,main/**/*ipcs.ts,renderer/**/*.tsx} : Define all Electron IPC channel types in `apps/desktop/src/shared/ipc-channels.ts` before implementing handlers

Applied to files:

  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/main/lib/analytics/index.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Use alias as defined in `tsconfig.json` when possible

Applied to files:

  • apps/desktop/src/preload/index.ts
  • apps/desktop/electron.vite.config.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`

Applied to files:

  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/**/*.{ts,tsx} : Move Node.js functionality needed in Electron renderer to `src/main/lib/` and communicate via IPC

Applied to files:

  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/main/lib/analytics/index.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/{renderer,lib/electron-router-dom.ts} : Never import Node.js modules in Electron renderer or shared code (`src/renderer/` and `src/lib/electron-router-dom.ts`)

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/main/**/*ipcs.ts : In Electron IPC handlers, always accept a single object parameter, not positional parameters, to maintain type safety

Applied to files:

  • apps/desktop/src/preload/index.ts
🧬 Code graph analysis (3)
apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx (2)
apps/desktop/src/main/lib/analytics/index.ts (1)
  • posthog (5-5)
apps/desktop/src/renderer/lib/posthog.ts (1)
  • posthog (6-6)
apps/desktop/src/renderer/screens/main/index.tsx (4)
apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts (1)
  • useVersionCheck (17-88)
apps/desktop/src/renderer/screens/main/components/Background.tsx (1)
  • Background (1-39)
apps/desktop/src/renderer/screens/main/components/AppFrame.tsx (1)
  • AppFrame (5-7)
apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx (1)
  • UpdateRequiredPage (19-122)
apps/desktop/src/lib/trpc/routers/auto-update/index.ts (1)
apps/desktop/src/main/lib/auto-updater.ts (1)
  • checkForUpdates (63-73)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Deploy Marketing
  • GitHub Check: Deploy Admin
  • GitHub Check: Deploy Web
  • GitHub Check: Deploy Docs
  • GitHub Check: Deploy API
  • GitHub Check: Build
🔇 Additional comments (12)
apps/desktop/src/main/lib/analytics/index.ts (2)

1-1: LGTM - Electron app module imported for version tracking.

The import is correctly placed and will be used to add version information to analytics events.


43-43: LGTM - Desktop version added to analytics tracking.

The addition of desktop_version using app.getVersion() provides consistent version tracking across analytics events in the main process, complementing the renderer-side tracking.

apps/desktop/src/lib/trpc/routers/auto-update/index.ts (1)

37-39: LGTM - Check mutation added to auto-update router.

The new check mutation correctly triggers the update check flow. Status updates are tracked via the existing subscription pattern, so no return value is needed.

apps/desktop/src/preload/index.ts (2)

4-4: LGTM - Global declaration for build-time version constant.

The declaration correctly types the __APP_VERSION__ global that will be defined by the Vite config at build time.


19-19: LGTM - App version exposed to renderer process.

The appVersion property correctly exposes the build-time version to the renderer via the preload bridge. Since Window.App is typed as typeof API (line 8), TypeScript will correctly infer the appVersion property.

apps/desktop/electron.vite.config.ts (2)

11-11: LGTM - Version imported from package.json.

Importing the version alongside existing imports is clean and allows it to be injected into the build as a constant.


140-140: LGTM - App version defined for preload at build time.

The __APP_VERSION__ define correctly injects the package.json version as a build-time constant in the preload bundle. Using JSON.stringify() ensures it's a valid string literal.

apps/desktop/src/renderer/screens/main/index.tsx (3)

40-46: LGTM - Version check integrated before authentication.

The version check is correctly positioned before the authentication check, ensuring outdated clients are blocked early in the flow. The destructured values (isLoading, isBlocked, requirements) provide clear state management for the version enforcement logic.


180-192: LGTM - Loading state during version verification.

Showing a loading spinner during the initial version check provides good UX and prevents users from seeing authentication flows before version verification completes.


194-203: LGTM - Update required page blocks outdated clients.

The version gate correctly blocks the app when isBlocked is true, displaying the update UI with clear version information. Accessing window.App.appVersion is safe here since it's exposed via the preload API.

apps/desktop/src/renderer/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx (1)

14-18: LGTM - Version tracking added to PostHog identification.

The addition of desktop_version to the PostHog identify call provides valuable analytics data and aligns with the version tracking added in the main process analytics. The appVersion property is properly typed through the API object exposed in the preload bridge.

apps/desktop/package.json (1)

112-112: semver@7.7.3 is secure and up-to-date.

Version 7.7.3 exists on npm and has no known security vulnerabilities. A previous ReDoS vulnerability (CVE-2022-25883) affected versions <7.5.2 but was patched in 7.5.2, so 7.7.3 is not affected.


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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx (1)

30-36: Consider handling mutation errors.

If checkMutation or installMutation fail at the tRPC/IPC level (distinct from auto-updater errors tracked in updateStatus), users receive no feedback. Consider adding onError callbacks or checking checkMutation.error / installMutation.error in the UI.

🔎 Example approach
 const handleCheckForUpdate = () => {
-  checkMutation.mutate();
+  checkMutation.mutate(undefined, {
+    onError: (err) => console.error("Failed to trigger update check:", err),
+  });
 };

 const handleInstall = () => {
-  installMutation.mutate();
+  installMutation.mutate(undefined, {
+    onError: (err) => console.error("Failed to trigger install:", err),
+  });
 };
apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts (2)

79-87: Inconsistent error handling between API errors and network errors.

When !response.ok, the hook fails open with error: null (lines 56-65). However, on network errors (catch block), it fails open but sets error to the caught error. This inconsistency could confuse consumers checking both isBlocked and error.

Consider either:

  1. Setting error: null here too (fully silent fail-open), or
  2. Creating an error for non-ok responses as well for consistent observability.
🔎 Option 1: Silent fail-open (consistent with non-ok handling)
     } catch (error) {
       // Fail open on network errors
       setState({
         isLoading: false,
         isBlocked: false,
         requirements: null,
-        error: error instanceof Error ? error : new Error("Unknown error"),
+        error: null,
       });
     }

47-88: Consider aborting fetch on unmount to prevent state updates after unmount.

If the component unmounts while fetch is in-flight, setState will be called on an unmounted component. While React 18+ handles this more gracefully, adding an AbortController would be cleaner and avoid potential memory leaks.

🔎 Example with AbortController
-  const checkVersion = useCallback(async () => {
+  const checkVersion = useCallback(async (signal?: AbortSignal) => {
     if (!hasVerified.current) {
       setState((prev) => ({ ...prev, isLoading: true }));
     }

     try {
-      const response = await fetch(`${API_BASE_URL}/api/desktop/version`);
+      const response = await fetch(`${API_BASE_URL}/api/desktop/version`, { signal });
       // ... rest of implementation
     } catch (error) {
+      if (error instanceof Error && error.name === "AbortError") {
+        return; // Silently ignore aborted requests
+      }
       // Fail open on network errors
       // ...
     }
   }, []);

   useEffect(() => {
+    const controller = new AbortController();
-    checkVersion();
+    checkVersion(controller.signal);

     const handleOnline = () => {
       if (!hasVerified.current) {
-        checkVersion();
+        checkVersion(controller.signal);
       }
     };

     window.addEventListener("online", handleOnline);
-    return () => window.removeEventListener("online", handleOnline);
+    return () => {
+      controller.abort();
+      window.removeEventListener("online", handleOnline);
+    };
   }, [checkVersion]);

Also applies to: 90-103

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42dc9ec and 61a1aba.

📒 Files selected for processing (10)
  • apps/api/src/app/api/desktop/version/route.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/env.d.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
🧰 Additional context used
📓 Path-based instructions (5)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/env.d.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/preload/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use type safety and avoid any types unless absolutely necessary in TypeScript files

Files:

  • apps/desktop/src/renderer/env.d.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/api/src/app/api/desktop/version/route.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/preload/index.ts
apps/desktop/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Move Node.js functionality needed in Electron renderer to src/main/lib/ and communicate via IPC

Files:

  • apps/desktop/src/renderer/env.d.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/preload/index.ts
apps/**/src/**/**/[A-Z]*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Structure component folders with one component per file using format ComponentName/ComponentName.tsx with index.ts barrel export

Files:

  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
apps/desktop/src/{shared/ipc-channels.ts,main/**/*ipcs.ts,renderer/**/*.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Define all Electron IPC channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers

Files:

  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/screens/main/index.tsx
🧠 Learnings (8)
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables in `src/main/index.ts` with `override: true` before any other imports in the desktop app

Applied to files:

  • apps/desktop/src/renderer/env.d.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Use alias as defined in `tsconfig.json` when possible

Applied to files:

  • apps/desktop/src/renderer/env.d.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/electron.vite.config.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/**/*.{ts,tsx} : Move Node.js functionality needed in Electron renderer to `src/main/lib/` and communicate via IPC

Applied to files:

  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/{shared/ipc-channels.ts,main/**/*ipcs.ts,renderer/**/*.tsx} : Define all Electron IPC channel types in `apps/desktop/src/shared/ipc-channels.ts` before implementing handlers

Applied to files:

  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/**/src/**/**/[A-Z]*.tsx : Structure component folders with one component per file using format `ComponentName/ComponentName.tsx` with `index.ts` barrel export

Applied to files:

  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/{renderer,lib/electron-router-dom.ts} : Never import Node.js modules in Electron renderer or shared code (`src/renderer/` and `src/lib/electron-router-dom.ts`)

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/main/**/*ipcs.ts : In Electron IPC handlers, always accept a single object parameter, not positional parameters, to maintain type safety

Applied to files:

  • apps/desktop/src/preload/index.ts
🧬 Code graph analysis (2)
apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx (3)
apps/desktop/src/shared/auto-update.ts (2)
  • AUTO_UPDATE_STATUS (1-7)
  • RELEASES_URL (12-12)
apps/desktop/src/renderer/screens/main/components/Background.tsx (1)
  • Background (1-39)
apps/desktop/src/renderer/screens/main/components/AppFrame.tsx (1)
  • AppFrame (5-7)
apps/desktop/src/lib/trpc/routers/auto-update/index.ts (1)
apps/desktop/src/main/lib/auto-updater.ts (1)
  • checkForUpdates (63-73)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Deploy API
  • GitHub Check: Deploy Admin
  • GitHub Check: Deploy Marketing
  • GitHub Check: Deploy Docs
  • GitHub Check: Deploy Web
  • GitHub Check: Build
🔇 Additional comments (15)
apps/desktop/src/renderer/hooks/useVersionCheck/index.ts (1)

1-1: LGTM!

Standard barrel export following the project's component structure conventions.

apps/desktop/src/renderer/env.d.ts (1)

3-3: LGTM!

Proper ambient type declaration for the Vite-injected global constant.

apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts (1)

1-1: LGTM!

Standard barrel export following the project's component structure conventions.

apps/desktop/src/preload/index.ts (1)

4-4: LGTM!

The implementation correctly exposes the build-time app version through the preload bridge, making it accessible to the renderer process via window.App.appVersion.

Also applies to: 19-19

apps/desktop/src/lib/trpc/routers/auto-update/index.ts (1)

37-39: LGTM!

The mutation correctly triggers the update check via tRPC IPC. The void return is appropriate since update status is communicated through the subscription mechanism (subscribe endpoint).

apps/desktop/electron.vite.config.ts (1)

11-11: LGTM!

The version injection is correctly configured for both preload and renderer processes, enabling version checks throughout the app.

Also applies to: 140-140, 179-180

apps/api/src/app/api/desktop/version/route.ts (2)

11-12: Hardcoded version constant is noted for future improvement.

The TODO correctly identifies that moving this to a database or environment variable would enable version updates without redeployment. This is a known limitation documented by the developer.


14-20: LGTM!

The endpoint structure is correct for Next.js App Router, and the response shape matches the requirements for the version check flow.

apps/desktop/src/renderer/screens/main/index.tsx (2)

40-46: LGTM!

Version check is correctly positioned before authentication, ensuring outdated clients are blocked early in the app lifecycle.


180-203: LGTM!

The loading and blocking UI flow is correctly implemented with proper null checks on versionRequirements before rendering the update page.

apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx (2)

1-6: LGTM!

Imports are well-organized. Good use of shared constants (AUTO_UPDATE_STATUS, RELEASES_URL) and alias paths per coding guidelines.


42-104: LGTM!

The UI implementation handles all states cleanly with appropriate loading indicators, error displays, and button states. Good use of the shared Background and AppFrame components for visual consistency.

apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts (3)

68-68: LGTM!

The window.App.appVersion access is correctly wired through the preload script as documented in the AI summary.


15-15: Environment variable is correctly configured. NEXT_PUBLIC_API_URL is properly injected in electron.vite.config.ts for the renderer build (line 154-157) via Vite's define mechanism, with a sensible fallback to https://api.superset.sh. The naming convention, while Next.js-styled, works correctly with electron-vite's build process.


21-34: The compareVersions function is adequate for the app's current numeric-only version format.

The function assumes numeric-only version parts and will produce incorrect results if versions include prerelease suffixes (e.g., "1.0.0-beta.1"). However, the app currently uses purely numeric versions ("0.0.39"), and both version sources—window.App.appVersion and the API response—are controlled internally, so this is not a practical concern. No changes needed unless the app's versioning strategy changes to include prerelease identifiers.

Comment thread apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 30, 2025

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ✅ Electric Fly.io app

Thank you for your contribution! 🎉

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts (2)

20-33: Semver comparison doesn't handle prerelease tags.

The Number() conversion will produce NaN for version parts containing non-numeric characters (e.g., "1.0.0-beta"Number("0-beta") = NaN). Comparisons with NaN are always false, which could lead to unexpected behavior.

If all versions will strictly follow numeric X.Y.Z format (as the current "0.0.39" suggests), this is fine. Otherwise, consider using a library like semver or adding explicit validation.


80-88: Minor: Error stored but fail-open means it's unused.

The error is captured in state, but since isBlocked is false on errors, the consuming component likely won't act on it. This is fine if you want the option to log or report errors later, but consider whether the error state adds value in a fail-open design.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61a1aba and 878ef5a.

📒 Files selected for processing (9)
  • apps/api/src/app/api/desktop/version/route.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use type safety and avoid any types unless absolutely necessary in TypeScript files

Files:

  • apps/api/src/app/api/desktop/version/route.ts
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
apps/desktop/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Move Node.js functionality needed in Electron renderer to src/main/lib/ and communicate via IPC

Files:

  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
🧬 Code graph analysis (1)
apps/desktop/src/lib/trpc/routers/auto-update/index.ts (1)
apps/desktop/src/main/lib/auto-updater.ts (1)
  • checkForUpdates (63-73)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Deploy API
  • GitHub Check: Deploy Docs
  • GitHub Check: Deploy Marketing
  • GitHub Check: Deploy Admin
  • GitHub Check: Deploy Web
  • GitHub Check: Build
🔇 Additional comments (3)
apps/desktop/src/lib/trpc/routers/auto-update/index.ts (1)

37-39: LGTM!

The new check mutation follows the established pattern of other mutations in this router and correctly delegates to the checkForUpdates function which handles its own error logging internally.

apps/api/src/app/api/desktop/version/route.ts (1)

1-12: LGTM - simple and effective endpoint.

The implementation is straightforward and correctly returns the minimum version requirement. The fail-open behavior on the client side means this endpoint being unavailable won't block users, which is the right tradeoff.

One minor consideration: if this version needs to change frequently or across environments, you might eventually want to source it from an environment variable. For now, the hardcoded constant is fine and makes the "how to force update" process clear.

apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts (1)

91-104: Good implementation of network reconnect handling.

The online event listener with the hasVerified guard ensures re-checks happen only when needed, and cleanup is properly handled. This aligns well with the PR's "re-check on reconnect" behavior.

Comment on lines +68 to +71
const requirements: VersionRequirements = await response.json();
const currentVersion = window.App.appVersion;
const isBlocked =
compareVersions(currentVersion, requirements.minimumVersion) < 0;
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.

⚠️ Potential issue | 🟡 Minor

Add defensive check for window.App.appVersion.

If window.App.appVersion is undefined (e.g., preload didn't initialize correctly), compareVersions would receive undefined and produce unexpected results due to NaN comparisons. Consider failing open gracefully when the current version cannot be determined.

🔎 Suggested defensive check
 			const requirements: VersionRequirements = await response.json();
 			const currentVersion = window.App.appVersion;
+
+			// Fail open if we can't determine the current version
+			if (!currentVersion) {
+				setState({
+					isLoading: false,
+					isBlocked: false,
+					requirements: null,
+					error: null,
+				});
+				return;
+			}
+
 			const isBlocked =
 				compareVersions(currentVersion, requirements.minimumVersion) < 0;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const requirements: VersionRequirements = await response.json();
const currentVersion = window.App.appVersion;
const isBlocked =
compareVersions(currentVersion, requirements.minimumVersion) < 0;
const requirements: VersionRequirements = await response.json();
const currentVersion = window.App.appVersion;
// Fail open if we can't determine the current version
if (!currentVersion) {
setState({
isLoading: false,
isBlocked: false,
requirements: null,
error: null,
});
return;
}
const isBlocked =
compareVersions(currentVersion, requirements.minimumVersion) < 0;
🤖 Prompt for AI Agents
In apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts around
lines 68 to 71, the code calls compareVersions with window.App.appVersion which
can be undefined; add a defensive check that reads and validates
window.App?.appVersion before calling compareVersions, and if it's missing or
not a string treat the check as "fail open" (set isBlocked = false) and
optionally log or warn about the missing version so the app does not mistakenly
block users when the preload didn't initialize.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/api/src/app/api/desktop/version/route.ts (1)

1-13: LGTM!

The endpoint is straightforward and correctly returns the minimum version. The fail-open design (desktop allows access if API is unreachable) handles availability concerns appropriately.

Consider moving MINIMUM_DESKTOP_VERSION to an environment variable for easier deployment-time changes without code modifications. However, the current approach with a hardcoded constant is acceptable since version bumps are typically tied to code releases anyway.

apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx (1)

35-39: Subscription error handling missing.

The subscription should handle potential connection errors to avoid silent failures. Consider adding an onError callback to gracefully handle subscription failures.

🔎 Proposed fix
 	// Subscribe to auto-update status changes
 	trpc.autoUpdate.subscribe.useSubscription(undefined, {
 		onData: (event) => {
 			setUpdateStatus({ status: event.status, error: event.error });
 		},
+		onError: (error) => {
+			console.error("[UpdateRequiredPage] Subscription error:", error);
+			setUpdateStatus({ status: AUTO_UPDATE_STATUS.ERROR, error: error.message });
+		},
 	});
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 878ef5a and 0e39477.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • apps/api/src/app/api/desktop/version/route.ts
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/package.json
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/desktop/src/renderer/hooks/useVersionCheck/useVersionCheck.ts
  • apps/desktop/src/renderer/hooks/useVersionCheck/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/index.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/electron.vite.config.ts
🧰 Additional context used
📓 Path-based instructions (5)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use type safety and avoid any types unless absolutely necessary in TypeScript files

Files:

  • apps/desktop/src/preload/index.ts
  • apps/api/src/app/api/desktop/version/route.ts
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
apps/desktop/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Move Node.js functionality needed in Electron renderer to src/main/lib/ and communicate via IPC

Files:

  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/lib/trpc/routers/auto-update/index.ts
  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
apps/**/src/**/**/[A-Z]*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Structure component folders with one component per file using format ComponentName/ComponentName.tsx with index.ts barrel export

Files:

  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
apps/desktop/src/{shared/ipc-channels.ts,main/**/*ipcs.ts,renderer/**/*.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Define all Electron IPC channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers

Files:

  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
🧠 Learnings (8)
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables in `src/main/index.ts` with `override: true` before any other imports in the desktop app

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/{shared/ipc-channels.ts,main/**/*ipcs.ts,renderer/**/*.tsx} : Define all Electron IPC channel types in `apps/desktop/src/shared/ipc-channels.ts` before implementing handlers

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Use alias as defined in `tsconfig.json` when possible

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/**/*.{ts,tsx} : Move Node.js functionality needed in Electron renderer to `src/main/lib/` and communicate via IPC

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/{renderer,lib/electron-router-dom.ts} : Never import Node.js modules in Electron renderer or shared code (`src/renderer/` and `src/lib/electron-router-dom.ts`)

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-28T01:56:39.031Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T01:56:39.031Z
Learning: Applies to apps/desktop/src/main/**/*ipcs.ts : In Electron IPC handlers, always accept a single object parameter, not positional parameters, to maintain type safety

Applied to files:

  • apps/desktop/src/preload/index.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from `trpc/server/observable` instead of async generators, as the library explicitly checks `isObservable(result)` and throws an error otherwise

Applied to files:

  • apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx
🧬 Code graph analysis (2)
apps/desktop/src/lib/trpc/routers/auto-update/index.ts (1)
apps/desktop/src/main/lib/auto-updater.ts (1)
  • checkForUpdates (63-73)
apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx (3)
apps/desktop/src/shared/auto-update.ts (3)
  • AutoUpdateStatus (9-10)
  • AUTO_UPDATE_STATUS (1-7)
  • RELEASES_URL (12-12)
apps/desktop/src/renderer/screens/main/components/Background.tsx (1)
  • Background (1-39)
apps/desktop/src/renderer/screens/main/components/AppFrame.tsx (1)
  • AppFrame (5-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Deploy Docs
  • GitHub Check: Deploy Admin
  • GitHub Check: Deploy API
  • GitHub Check: Deploy Marketing
  • GitHub Check: Deploy Web
  • GitHub Check: Build
🔇 Additional comments (5)
apps/desktop/package.json (1)

112-112: LGTM!

The semver package is the appropriate choice for semantic version comparison. The runtime dependency pairs correctly with the existing @types/semver dev dependency.

apps/desktop/src/preload/index.ts (2)

4-5: LGTM!

Build-time constant declaration for the app version injected via Vite define.


19-19: LGTM!

Correctly exposes the app version to the renderer via contextBridge. This follows the standard Electron pattern for exposing static values and integrates cleanly with the existing API object.

apps/desktop/src/lib/trpc/routers/auto-update/index.ts (1)

37-39: LGTM!

The check mutation follows the existing patterns in this router and correctly delegates to checkForUpdates(). As per coding guidelines, tRPC is appropriately used for this IPC communication.

apps/desktop/src/renderer/components/UpdateRequiredPage/UpdateRequiredPage.tsx (1)

59-121: LGTM!

The component UI is well-structured with clear visual hierarchy, proper loading states, and fallback messaging. The conditional rendering between "Install & Restart" and "Check for Update" buttons correctly reflects the update lifecycle.

Add ability to force desktop users to update when breaking changes are
deployed. The app checks version requirements from the API on startup
and blocks usage if outdated.

Changes:
- Add GET /api/desktop/version endpoint returning minimum version
- Add useVersionCheck hook with network reconnection handling
- Add UpdateRequiredPage component for blocking UI
- Add version gate in MainScreen before auth check
- Expose app version via window.App.appVersion
- Add check mutation to auto-update tRPC router

Behavior:
- Checks version on startup
- Re-checks when network comes back online (if not verified)
- Fail-open on network errors (allows offline use)
- Uses existing auto-updater for install flow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@saddlepaddle saddlepaddle merged commit f0dff09 into main Dec 30, 2025
13 checks passed
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