Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions apps/web/src/versionSkew.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
buildVersionMismatchDismissalKey,
dismissVersionMismatch,
isVersionMismatchDismissed,
isClientBehindServer,
resolveServerConfigVersionMismatch,
resolveServerSelfUpdateCapability,
resolveVersionMismatch,
Expand All @@ -26,7 +27,10 @@ describe("versionSkew", () => {
});
});

it("reads the server version from config descriptors", () => {
it("does not offer a server update when this client is older than the server", () => {
expect(
isClientBehindServer("0.0.34-nightly.20260814.1090", "0.0.34-nightly.20260814.1092"),
).toBe(true);
expect(
resolveServerConfigVersionMismatch({
environment: {
Expand All @@ -42,8 +46,27 @@ describe("versionSkew", () => {
},
},
}),
).toBeNull();
});

it("reads an older server version from config descriptors", () => {
expect(
resolveServerConfigVersionMismatch({
environment: {
environmentId: EnvironmentId.make("environment-1"),
label: "Remote",
platform: {
os: "darwin",
arch: "arm64",
},
serverVersion: "0.0.0-old",
capabilities: {
repositoryIdentity: true,
},
},
}),
).toMatchObject({
serverVersion: "9.9.9",
serverVersion: "0.0.0-old",
});
});

Expand Down
13 changes: 12 additions & 1 deletion apps/web/src/versionSkew.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { EnvironmentId, ServerConfig, ServerSelfUpdateCapability } from "@t3tools/contracts";
import { compareSemverVersions } from "@t3tools/shared/semver";
import * as Schema from "effect/Schema";

import { APP_VERSION } from "./branding";
Expand Down Expand Up @@ -43,10 +44,20 @@ export function resolveVersionMismatch(
};
}

export function isClientBehindServer(clientVersion: string, serverVersion: string): boolean {
return compareSemverVersions(clientVersion, serverVersion) < 0;
}

export function resolveServerConfigVersionMismatch(
serverConfig: Pick<ServerConfig, "environment"> | null | undefined,
): VersionMismatch | null {
return resolveVersionMismatch(serverConfig?.environment.serverVersion);
const mismatch = resolveVersionMismatch(serverConfig?.environment.serverVersion);
// The desktop app already surfaces its own update in the sidebar. A newer
// server should not look like a server update, or offer a downgrade.
if (!mismatch || isClientBehindServer(mismatch.clientVersion, mismatch.serverVersion)) {
return null;
}
return mismatch;

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.

Client-behind skew silently dropped

Medium Severity

resolveServerConfigVersionMismatch returns null when the client is older than the server, which hides the composer and Connections skew UI entirely. The PR title and description call for offering a client update (Reload on web, Download/Install on desktop), but nothing replaces the suppressed banner. Web has no sidebar updater, and the desktop updater tracks the release feed—not the connected serverVersion—so users can stay silently skewed with no affordance to catch up.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a1ba518. Configure here.

}

/** The update path the connected server offers, or null when it only
Expand Down
4 changes: 3 additions & 1 deletion docs/user/updating.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Keeping T3 Code in Sync

The T3 Code web or desktop app and the server it connects to work best when they use the same
version. If they do not match, T3 Code shows a warning with the right update option for that server.
version. If the server is older, T3 Code shows a warning with the right update option for that
server. If this app is older, the desktop update indicator in the sidebar is the place to update;
T3 Code does not offer to move the server backward.

## Where to Find the Update

Expand Down
Loading