fix(site/src/pages/DeploymentSettingsPage): gate browser-only paywall on entitlement by david-fraley · Pull Request #28660 · coder/coder · GitHub
Skip to content

fix(site/src/pages/DeploymentSettingsPage): gate browser-only paywall on entitlement - #28660

Merged
david-fraley merged 1 commit into
mainfrom
dfraley/devex-828-browser-only-paywall-entitlement
Aug 26, 2026
Merged

fix(site/src/pages/DeploymentSettingsPage): gate browser-only paywall on entitlement#28660
david-fraley merged 1 commit into
mainfrom
dfraley/devex-828-browser-only-paywall-entitlement

Conversation

@david-fraley

@david-fraley david-fraley commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

DEVEX-828

TL;DR

If you already paid for Coder, stop showing you an ad asking you to pay for Coder.

The Security settings page was showing the "upgrade to Premium" box to customers who already have Premium. It now only shows to deployments with no license.

Problem

The Security settings page rendered the premium paywall whenever entitlements.features.browser_only.enabled was false:

featureBrowserOnlyEnabled={entitlements.features.browser_only.enabled}
...
{!featureBrowserOnlyEnabled ? <PremiumPaywallSmall ... /> : null}

Feature.Enabled is not "the license covers this feature". For browser_only the server sets it from the deployment's own config:

// enterprise/coderd/coderd.go
codersdk.FeatureBrowserOnly: api.BrowserOnly,

license.LicensesEntitlements then only forces Enabled to false when the feature is not entitled. So enabled === true requires a license and CODER_BROWSER_ONLY=true, and any licensed premium or trial deployment that leaves browser-only connections turned off (the default) was shown an upgrade paywall for a feature it already owns.

Fix

Gate the paywall on the entitlement and keep enabled for the Enabled/Disabled badge, matching the pattern already used by the External Auth settings page:

isBrowserOnlyEntitled={
  entitlements.features.browser_only.entitlement !== "not_entitled"
}

grace_period counts as entitled, so expiring licenses do not flip to a paywall either.

Verified against license.LicensesEntitlements with CODER_BROWSER_ONLY off, which is the state in the report:

Deployment entitlement enabled Paywall before Paywall after
Community (no license) not_entitled false shown shown
Premium trial entitled false shown hidden
Premium entitled false shown hidden
Enterprise entitled false shown hidden
Premium, grace period grace_period false shown hidden

With browser-only turned on, entitled deployments keep the Enabled badge and no paywall.

Proof

Before, premium license with browser-only connections turned off:

paywall shown on a licensed deployment

After, same state:

no paywall on a licensed deployment

After, community deployment still gets the paywall:

paywall shown on a community deployment

Both states are covered by new play assertions in SecuritySettingsPageView.stories.tsx (EntitledAndTurnedOff, NotEntitled).

Notes

  • Overlaps with fix: remove premium paywall for browser-only connections #28658, which removes the paywall from this page entirely. This PR keeps the paywall for community deployments and only stops it from showing on licensed ones.
  • Out of scope: this page hardcodes canViewPremium, while other paywall surfaces pass permissions.viewAllLicenses.
Investigation notes
  1. SecuritySettingsPage.tsx passed entitlements.features.browser_only.enabled into the view as the paywall condition.
  2. enterprise/coderd/coderd.go builds the enablements map from deployment config, so browser_only enablement is api.BrowserOnly (CODER_BROWSER_ONLY).
  3. enterprise/coderd/license/license.go applies Enabled: enablements[featureName] || featureName.AlwaysEnable() for licensed features and only downgrades Enabled to false for not-entitled features. Entitlement and enablement are therefore independent signals, and only entitlement should drive an upgrade prompt.
  4. ExternalAuthSettingsPageView and AppearanceSettingsPage already gate their paywalls on entitlement !== "not_entitled"; this page was the outlier.

Generated by Coder Agents on behalf of @david-fraley.

… on entitlement

The Security settings page showed the premium paywall whenever the browser_only feature was not enabled. Enabled means the deployment turned browser-only connections on (CODER_BROWSER_ONLY), so licensed premium and trial deployments that leave the feature off saw an upgrade paywall for a feature they already have.

Gate the paywall on the browser_only entitlement instead, keeping the enabled flag for the Enabled/Disabled badge.
@linear-code

linear-code Bot commented Aug 26, 2026

Copy link
Copy Markdown

@david-fraley
david-fraley marked this pull request as ready for review August 26, 2026 19:15
@david-fraley
david-fraley enabled auto-merge (squash) August 26, 2026 19:18
@david-fraley
david-fraley disabled auto-merge August 26, 2026 19:18

@jeremyruppel jeremyruppel left a comment

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.

LGTM 👍

@untra untra left a comment

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.

paywall keyed off of entitled features.browser_only entitlement , not just if it's enabled 👍

@david-fraley
david-fraley merged commit fc35aae into main Aug 26, 2026
61 of 62 checks passed
@david-fraley
david-fraley deleted the dfraley/devex-828-browser-only-paywall-entitlement branch August 26, 2026 19:27
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants