How OpenWork Implements Version Gating for Desktop Application Updates

OpenWork implements version gating through a double-gated mechanism that validates desktop updates against both Den-published version metadata and organization-specific allowedDesktopVersions policies defined in apps/app/src/app/lib/version-gate.ts.

OpenWork, maintained by the repository different-ai/openwork, controls desktop application updates using a robust version gating system that prevents unauthorized builds from reaching production environments. This architecture ensures that updates satisfy both global service constraints and local organizational policies before installation. The implementation centers on a TypeScript validation layer that parses semantic versions and enforces multi-tiered deployment rules across the stack.

The Double-Gated Architecture

OpenWork’s version gating relies on two distinct sources of truth that work in sequence:

  1. Den service metadata – The Den backend publishes the latest supported app version, minimum required version, and a canonical list of publishedDesktopVersions representing officially released builds.
  2. Organization-level policy – Each tenant can optionally define an allowedDesktopVersions array and an allowAlphaUpdates boolean in their desktop configuration, restricting updates to an explicit subset of Den-published versions.

An update only passes the gate if it appears in the Den-published list and complies with the requesting organization’s specific policy constraints.

Parsing and Comparing Semantic Versions

Normalizing Version Strings

The parseComparableVersion function in apps/app/src/app/lib/version-gate.ts (line 41) normalizes arbitrary version strings into structured components. It accepts inputs with optional leading v characters and prerelease identifiers (such as -alpha or -beta), splitting each version into a numeric release array and a prerelease array for subsequent comparison.

Semantic Comparison Logic

The compareVersions function (line 77) implements the comparison logic used throughout the gating system. It first evaluates the numeric release parts (major, minor, patch), then falls back to comparePrereleaseIdentifiers for semver-style prerelease comparison. The function returns -1, 0, or 1 to indicate relative ordering, enabling strict validation of version precedence.

Validating Against Den Service Metadata

Fetching Fresh Metadata

Before evaluating an update candidate, the client calls readFreshDenAppVersionMetadata (line 123) to contact the Den service at /app-version-metadata. This endpoint returns critical bounds including latestAppVersion (the newest supported release), minAppVersion (the oldest allowed client), and the complete array of publishedDesktopVersions.

Enforcing Global Limits

The isUpdateSupportedByDen function (line 184) applies the global service constraints. It compares the candidate version against Den’s latestAppVersion, permitting the update only if the candidate is less than or equal to the latest known stable version. This prevents clients from installing builds that exceed the globally recognized release threshold.

Enforcing Organization-Level Policies

Restricting Versions with Allow Lists

The isUpdateAllowedByDesktopConfig function (line 106) implements the organizational policy layer. If the configuration includes an allowedDesktopVersions array, the candidate must match one entry exactly to proceed. If the array is absent, the function defaults to permitting all Den-published versions, maintaining backward compatibility for organizations without custom policies.

Alpha Channel Access

For prerelease testing, isAlphaUpdateAllowed (line 210) provides controlled access to alpha builds. When allowAlphaUpdates is enabled, the function permits installation of alpha versions that are exactly one patch ahead of the organization’s maximum allowed stable version. This enables staged beta testing without exposing arbitrary prerelease builds.

The Complete Gating Flow

The isUpdateAllowed Entry Point

The isUpdateAllowed function (line 238) serves as the single entry point for the React-based updater flow. It orchestrates the double-gated validation by first invoking isUpdateAllowedByDesktopConfig to verify organizational policy, then calling isUpdateSupportedByDen to confirm global service support. Only candidates satisfying both checks receive installation approval.

Selecting Stable Updates

The selectStableDesktopUpdate function (line 149) handles automatic update selection. It constructs the set of published desktop versions, filters them through the organization’s allow list, and selects the highest permissible version that is newer than the currently installed build. The function returns a structured result indicating whether an update is available, blocked by policy, or unnecessary because the current version is current.

Generating the Canonical Published Version List

The list of valid desktop versions originates from scripts/release/generate-desktop-versions.mjs, a release automation script that maintains the Den service’s source of truth:

  • buildPublishedDesktopVersions (line 24) scans Git tags for vX.Y.Z patterns, validates them as semantic versions, and merges them with any previously generated list.
  • renderDesktopVersionsFile (line 45) emits a TypeScript constant named PUBLISHED_DESKTOP_VERSIONS to ee/apps/den-api/src/generated/desktop-versions.ts, which Den consumes at runtime.
  • The script filters out versions older than MIN_SUPPORTED_DESKTOP_VERSION (currently 0.17.0), ensuring the service only references actively supported releases.

Implementation Examples

// Determine if a candidate version may be offered to the user
import { isUpdateAllowed } from "./app/lib/version-gate";
import { readDenSettings } from "./app/lib/den";

async function canShowUpdate(candidate: string): Promise<boolean> {
  // Load the organization's desktop configuration from Den (cached in localStorage)
  const settings = readDenSettings();               // ← apps/app/src/app/lib/den.ts#L57
  const desktopConfig = await fetchDenDesktopConfig(settings); // user-defined helper
  return await isUpdateAllowed(candidate, desktopConfig);
}
// Pick the newest stable update that satisfies both Den and org policies
import { selectStableDesktopUpdate } from "./app/lib/version-gate";

async function getRecommendedUpdate(currentVersion: string) {
  const desktopConfig = await fetchDenDesktopConfig(); // retrieve from Den
  const latestVersion = "0.20.3"; // fetched from Den's metadata endpoint
  const target = await selectStableDesktopUpdate({
    currentVersion,
    latestVersion,
    desktopConfig,
  });
  // `target` is either a string (the version to update to) or null (no update)
  return target;
}

Summary

  • Double-gated validation ensures updates are both Den-published and org-approved via isUpdateAllowed in apps/app/src/app/lib/version-gate.ts.
  • Semantic parsing uses parseComparableVersion and compareVersions to handle prerelease identifiers and version precedence correctly.
  • Organization policies restrict deployments through allowedDesktopVersions arrays and allowAlphaUpdates flags.
  • Alpha handling permits controlled access to prerelease builds exactly one patch ahead of the maximum stable version.
  • Version list generation occurs via scripts/release/generate-desktop-versions.mjs, which produces the PUBLISHED_DESKTOP_VERSIONS constant consumed by the Den service.

Frequently Asked Questions

What is the role of the Den service in OpenWork's version gating?

The Den service acts as the global authority for desktop application updates by publishing latestAppVersion, minAppVersion, and the canonical publishedDesktopVersions list. According to the OpenWork source code, the desktop client queries Den via readFreshDenAppVersionMetadata to obtain these boundaries, ensuring no client installs a build newer than the globally recognized latest version or older than the minimum supported threshold.

How does OpenWork handle alpha or prerelease desktop updates?

OpenWork permits alpha updates through the isAlphaUpdateAllowed function when an organization explicitly sets allowAlphaUpdates: true in their desktop configuration. As implemented in apps/app/src/app/lib/version-gate.ts, this allows installation of alpha builds that are exactly one patch version ahead of the organization's current maximum allowed stable version, enabling controlled beta testing without exposing arbitrary prerelease tags.

Can organizations block specific desktop versions from being installed?

Yes. Organizations can define an allowedDesktopVersions array in their desktop policy configuration. The isUpdateAllowedByDesktopConfig function enforces this restriction by requiring candidate versions to match an entry in the array exactly; if the array is present, any version not explicitly listed is blocked, enabling staged rollouts, forced rollbacks, or phased deployments.

Where does OpenWork store the list of officially published desktop versions?

The canonical list is generated by scripts/release/generate-desktop-versions.mjs during the release process and stored as the PUBLISHED_DESKTOP_VERSIONS constant in ee/apps/den-api/src/generated/desktop-versions.ts. This file is consumed by the Den service at runtime to validate that update candidates correspond to actual Git-tagged releases in the repository.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →