Skip to content

[Bug] UpgradeBadge and UpgradeButton render to non-owner users in the sidebar #1524

Description

@Harsh23Kashyap

[Bug] UpgradeBadge and UpgradeButton render to non-owner users in the sidebar

Problem

The UpgradeBadge (shown next to feature-gated nav items in the sidebar) and the UpgradeButton (shown in the sidebar footer) render to any signed-in user, not just to the org's OWNER. A MEMBER (or even a former owner who lost the role) sees the same "Upgrade to Pro" prompts that are intended for the billing decision-maker.

The settings pages already do the right thing (they're OWNER-gated via authenticatedPage(..., { minRole: OrgRole.OWNER, ... })), so the upsell cards inside /settings/security and /settings/audit are only seen by owners. But the sidebar is shared across all users and has no such check.

The defaultSidebar/index.tsx already computes isOwner for the connection-stats notification dot, so the auth context is available — it just isn't being threaded down to the upgrade UI.

Background

Files affected:

  • packages/web/src/app/(app)/@sidebar/components/sidebarBase.tsx:117<UpgradeButton /> shown to all users when !isValidLicenseActive.
  • packages/web/src/app/(app)/@sidebar/components/defaultSidebar/nav.tsx:123-134<UpgradeBadge /> shown to all users missing the required entitlement.
  • packages/web/src/app/(app)/@sidebar/components/settingsSidebar/nav.tsx:87-97 — same pattern in the settings sidebar.
  • packages/web/src/app/(app)/@sidebar/components/defaultSidebar/index.tsx:43 — already computes isOwner (just not threaded down).
  • packages/web/src/app/(app)/@sidebar/components/settingsSidebar/index.tsx — does not compute isOwner at all yet.

Current behavior

A MEMBER signed into a Sourcebot instance without a Pro license sees:

  1. An "Upgrade to Pro" button at the bottom of every page (in the sidebar footer).
  2. A small "Upgrade" badge next to the API Keys, SSO, SCIM, Audit, and MCP nav items in the settings sidebar.

A MEMBER cannot act on either of these — both link to the upgrade flow which is only meaningful for owners.

Expected behavior

Both the UpgradeButton and the UpgradeBadge should be hidden for any user whose role is not OrgRole.OWNER. The settings pages already do this correctly; the sidebar should match.

Proposed solution

  1. Add an isOwner?: boolean prop to SidebarBaseProps and NavProps (in defaultSidebar and settingsSidebar).
  2. In SidebarBase, change !isValidLicenseActive && <UpgradeButton /> to isOwner && !isValidLicenseActive && <UpgradeButton />.
  3. In each Nav component, change showUpgradeBadge to require isOwner === true in addition to the entitlement check.
  4. In defaultSidebar/index.tsx, pass isOwner={isOwner} to <Nav> and <SidebarBase> (the value is already computed at line 43).
  5. In settingsSidebar/index.tsx, compute isOwner (using the same getAuthContext + OrgRole.OWNER pattern as defaultSidebar) and pass it to <Nav> and <SidebarBase>.
  6. Add a vitest case for the Nav component to lock in the behaviour: badge is rendered for isOwner={true} + missing entitlement, and not rendered for isOwner={false}.

Alternatives considered

  • Hide the entire sidebar for non-owners. Rejected: the search nav items are useful for non-owners, and the rest of the sidebar is a perfectly normal product surface. The upgrade UI is the only thing that should be gated.
  • Move the upgrade prompt to a banner shown only on the owner's dashboard. Larger change; the issue is specifically about the sidebar pop-up.
  • Make UpgradeBadge itself check the role internally. The badge component is a tiny presentational element; gating belongs in the parent Nav so all callers (default and settings) get the same behaviour without each importing the auth context.

Scope

  • 4 files modified (sidebarBase.tsx, defaultSidebar/nav.tsx, defaultSidebar/index.tsx, settingsSidebar/nav.tsx, settingsSidebar/index.tsx).
  • 1 new test file (defaultSidebar/nav.test.tsx) with 2 vitest cases.
  • No schema, no dependency, no migration. Pure frontend fix.

Acceptance criteria

  • UpgradeButton is not rendered for a signed-in user whose role is MEMBER (or who is not signed in).
  • UpgradeBadge is not rendered for a signed-in user whose role is MEMBER (or who is not signed in), in either the default or settings sidebar.
  • Both are still rendered for OWNERs in the current scenarios.
  • Existing tests still pass; new tests cover the new behaviour.

Backward compatibility

Pure UI behaviour change. No API, no schema. Existing users on the OWNER role see no change. Non-owner users stop seeing the prompts they couldn't act on.

Risks

Minimal. The settings pages already gate on OWNER, so the upsell cards inside /settings/security and /settings/audit are unaffected. The only behaviour change is in the sidebar, which is shared UI.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions