# How Desktop Policies in OpenWork Restrict Local Model Access

> Discover how OpenWork desktop policies restrict local model access by enforcing rules via the DesktopAppRestrictionChecker. Learn to manage your organization's AI capabilities effectively.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: how-to-guide
- Published: 2026-08-16

---

**OpenWork employs a desktop-policy system that governs local model capabilities by calculating an effective policy from organization settings and default values, then enforcing these rules through a `DesktopAppRestrictionChecker` that gates UI features and backend operations.**

OpenWork is an open-source AI workbench that organizes model access through centrally managed desktop policies. These policies allow organizations to restrict which local model features—such as custom providers or Zen models—are available to users on their machines. By combining a static policy catalog with runtime calculation of effective permissions, OpenWork ensures that security and licensing constraints propagate seamlessly from the cloud backend to the desktop client.

## Policy Catalog and Definition

The foundation of the restriction system is a static catalog defined in [`packages/types/src/den/desktop-policies.ts`](https://github.com/different-ai/openwork/blob/main/packages/types/src/den/desktop-policies.ts). This file exports `desktopPolicyDefinitions`, an array of policy objects that specify every controllable feature. Each entry includes an `id`, human-readable `name` and `description`, a `userNotice` string displayed when the policy blocks access, and a `defaultValue` boolean applied when no organization-specific policy exists.

Key policy IDs that control local model access include:

- **`allowCustomProviders`** – Governs whether users can add non-cloud model endpoints.
- **`allowZenModel`** – Controls visibility of built-in Zen models in the model picker.

## Policy Storage and Retrieval

Policies are stored in the Den backend as JSON documents typed as `DesktopPolicyDocument`. When the desktop client initializes, it fetches two sources:

1. The **default policy** applied to all users without explicit organization overrides.
2. Any **assigned policies** linked to the signed-in organization.

These raw documents are normalized using `normalizeDesktopPolicyDocument()` before being passed to the effective policy calculator.

## Calculating Effective Permissions

The core logic for determining what a user can access lives in the `calculateEffectiveDesktopPolicy()` function exported from [`desktop-policies.ts`](https://github.com/different-ai/openwork/blob/main/desktop-policies.ts). This utility accepts the default policy, an array of assigned policies, and the organization policy count, then produces a `Required<DesktopPolicyValue>` object representing the final permissions.

The calculation follows an inclusive OR logic: a feature is enabled if **any** policy explicitly sets its value to `true`. If the organization has no assigned policies (`orgPolicyCount === 0`), the system grants full access by invoking `allDesktopPolicies(true)`.

```typescript
import { calculateEffectiveDesktopPolicy } from "./desktop-policies";

const effective = calculateEffectiveDesktopPolicy({
  orgPolicyCount: orgPolicies.length,
  defaultPolicy: defaultPolicy,
  assignedPolicies: orgPolicies,
});

```

## Runtime Enforcement with DesktopAppRestrictionChecker

Once calculated, the effective policy is wrapped in a `DesktopAppRestrictionChecker` function injected throughout the UI layer. This checker, constructed in [`apps/app/src/react-app/domains/connections/policy-provider-reconcile.ts`](https://github.com/different-ai/openwork/blob/main/apps/app/src/react-app/domains/connections/policy-provider-reconcile.ts), provides a simple interface:

```typescript
type DesktopAppRestrictionChecker = (opts: { restriction: DesktopPolicyKey }) => boolean;

const checkDesktopAppRestriction: DesktopAppRestrictionChecker = ({ restriction }) =>
  effective[restriction] === true;

```

Components call this checker to conditionally render features. For example, the model picker in [`apps/app/src/react-app/domains/connections/provider-auth/store.ts`](https://github.com/different-ai/openwork/blob/main/apps/app/src/react-app/domains/connections/provider-auth/store.ts) queries the checker before displaying the "Add custom provider" button.

### Blocking Custom Providers

When the `allowCustomProviders` policy evaluates to `false`, OpenWork implements a defense-in-depth strategy. The UI hides the relevant controls and displays the `userNotice` defined in the catalog: *"Your organization administrator has disabled adding custom providers."* Simultaneously, the backend rejects any MCP (Model Context Protocol) requests attempting to register non-cloud model endpoints, ensuring users cannot bypass UI restrictions via API calls.

### Filtering Zen Models

Similarly, the `allowZenModel` policy filters the available model list. When disabled, built-in Zen models are removed from the picker before the UI renders, effectively restricting local access to these specific weights even if they are physically present on the machine.

## Updating Policies via MCP

Administrators modify desktop policies through the MCP endpoint `/v1/desktop-policies/:id`. The client detects these changes via the policy reconciliation loop tested in [`evals/flows/desktop-policies-cloud-mcp.flow.ts`](https://github.com/different-ai/openwork/blob/main/evals/flows/desktop-policies-cloud-mcp.flow.ts). Upon detecting an update, the desktop client:

1. Re-fetches the policy documents from the Den backend.
2. Re-runs `calculateEffectiveDesktopPolicy()`.
3. Propagates the new `DesktopAppRestrictionChecker` to all subscribed UI components.

This reactive pattern ensures that disabling `allowCustomProviders` immediately hides the custom provider UI across all open windows without requiring an application restart.

## Summary

- **Policy Catalog:** Static definitions in [`desktop-policies.ts`](https://github.com/different-ai/openwork/blob/main/desktop-policies.ts) define restrictable features like `allowCustomProviders` and `allowZenModel` with default values and user-facing notices.
- **Effective Calculation:** The `calculateEffectiveDesktopPolicy()` function merges default and organization policies using inclusive OR logic, defaulting to full access when no org policies exist.
- **UI Enforcement:** A `DesktopAppRestrictionChecker` constructed in [`policy-provider-reconcile.ts`](https://github.com/different-ai/openwork/blob/main/policy-provider-reconcile.ts) gates component rendering, while the backend validates MCP requests to prevent circumvention.
- **Dynamic Updates:** Policies are patched via MCP endpoints and re-reconciled automatically, enabling real-time restriction of local model access without client restarts.

## Frequently Asked Questions

### What happens if an organization has no desktop policies assigned?

When `orgPolicyCount` is zero, `calculateEffectiveDesktopPolicy()` returns `allDesktopPolicies(true)`, granting the user full access to all local model features. This ensures backward compatibility and avoids accidentally locking out users during initial setup.

### How does OpenWork prevent users from bypassing UI restrictions to add custom providers?

The restriction is enforced at two layers. The UI layer uses `checkDesktopAppRestriction({ restriction: "allowCustomProviders" })` to hide the add-provider controls, while the backend layer validates incoming MCP requests against the same policy. If the policy is disabled, the server rejects the request regardless of what the UI displays.

### Can individual users override desktop policies on their local machine?

No. Because the effective policy is calculated from organization-assigned documents stored in the Den backend and fetched at runtime, local modifications cannot override the server-side configuration. The desktop client treats these policies as read-only authority for feature gating.

### Where can I find the end-to-end tests verifying policy enforcement?

The file [`evals/flows/desktop-policies-cloud-mcp.flow.ts`](https://github.com/different-ai/openwork/blob/main/evals/flows/desktop-policies-cloud-mcp.flow.ts) contains the primary E2E test suite that exercises the full lifecycle: patching a policy via MCP, re-reading it on the client, and verifying UI reactions. Unit tests for specific provider restrictions are located in [`evals/specs/models-available.slow.test.ts`](https://github.com/different-ai/openwork/blob/main/evals/specs/models-available.slow.test.ts).