Today Platform Web — Dev Docs
Architecture

Cross-platform headers

How web and Electron identify Linux, macOS, and Windows requests with X-Client-Platform and X-App-Version, including the Linux cloud rollout boundary.

Requests made by apps/web carry two client-identification headers:

HeaderBrowser valueElectron valueWhy
X-Client-Platformweblinux-client, macos-client, or windows-clientSelects the client platform for routing and telemetry
X-App-Version2.0.0The packaged desktop application versionLets cloud gates target specific client versions

The browser defaults live in packages/api-client/src/platform-constants.ts:

export const APP_VERSION_HEADER_VALUE = '2.0.0'
export const CLIENT_PLATFORM_HEADER_VALUE = 'web'

Inside the Electron app shell, the validated document-start runtime descriptor overrides those defaults. The mapping is explicit:

Bridge platformAPI headerDevice registration identity
linuxlinux-clientlinux / linux-connector / linux
macosmacos-clientmacos / macos-connector / darwin
windowswindows-clientwindows / windows-connector / win32

linux-connector is a cloud device clientType; it is not an X-Client-Platform value. The web/API header remains linux-client.

Why the contract is symmetric

Web, native mobile clients, and the desktop app all use the same two headers with platform-specific values. Cloud services can use them for:

  • Auth-context platform routing — downstream services receive a normalized first-party platform when the API middleware recognizes it.
  • Version-gated features — routes behind a minimum-client-version gate compare X-App-Version with the configured minimum.
  • Telemetry segmentation — platform and version are explicit rather than inferred from user-agent strings.

New browser routes inherit web; a new platform identifier still requires a coordinated cloud rollout.

Where the headers are injected

The shared browser-side context lives in:

FileWhat it does
apps/web/src/lib/client-runtime.tsResolves web vs Electron platform, app version, and device ID
apps/web/src/lib/client-context-headers.tsApplies the shared browser/API request context
apps/web/src/hooks/use-api-client.tsConfigures the generated API client
apps/web/src/hooks/use-session.tsApplies the same context to session/token requests
apps/web/src/lib/chat/protocol/agent-client.tsApplies the runtime values to agent messages

Electron also sets the authoritative platform/version headers in the main process for trusted Today requests and uses the same values for device registration, tool synchronization, and relay connections. This prevents page code from downgrading a Linux package to the generic web identity.

The normal browser path is:

const headers = new Headers()
applyClientContextHeaders(headers)

// Browser:
// X-Client-Platform: web
// X-App-Version: 2.0.0

// Linux Electron:
// X-Client-Platform: linux-client
// X-App-Version: <packaged application version>

Linux cloud rollout boundary

The client-side Linux contract is implemented, but it does not imply production cloud enablement:

  • The current API platform normalizer recognizes ios, android, web, web-client, macos, windows, and web-bff. Suffix-bearing values such as macos-client and windows-client normalize through their base platform. linux-client currently has no recognized linux base, so the API omits the platform from downstream auth context. It does not reject an otherwise valid bearer token solely because of that unknown platform value.
  • The cloud device registry has linux and linux-connector schemas, but accepts that pair only in the dev environment when LINUX_DEVICE_REGISTRATION_ENABLED is enabled. The production flag remains disabled.

Before production Linux remote tools are enabled, cloud must add Linux to API platform normalization and deliberately open the device-registration gate. Until then, Linux packages and the local Electron bridge can be built and tested, while production platform-specific routing, telemetry, and remote connector/tool registration remain unavailable.

Version-bump policy

The browser fallback X-App-Version is currently '2.0.0'. Desktop packages use their packaged version instead.

Bump APP_VERSION_HEADER_VALUE only when a future browser-facing cloud gate requires it. A typical coordinated change is:

  1. Cloud raises a new gate, for example minimum version 2.1.0.
  2. Web bumps APP_VERSION_HEADER_VALUE to 2.1.0 in the same rollout.
  3. The PR makes the cloud-gate dependency explicit so the server side ships first.

Desktop release versions follow the desktop release workflow and do not require changing the browser constant.

Missing or unrecognized values

A missing or unrecognized X-Client-Platform is omitted from normalized downstream context. Authentication still depends on the route's bearer/session contract, but platform-specific routing and telemetry cannot rely on the value.

For routes with an active version gate, a missing or below-minimum X-App-Version can return 426 Upgrade Required. Inspect the captured response for the exact gate and minimum version rather than assuming every route enforces the same policy.

On this page