Skip to content

Conversation

geropl
Copy link
Member

@geropl geropl commented Oct 14, 2025

What this PR does

Implements feature flag-based blocking for Gitpod Classic PAYG users to support the sunset process.

Backend Changes

  • Utility functions in featureflags.ts:
    • getClassicPaygSunsetConfig() - fetches feature flag configuration
    • isUserBlockedBySunset() - determines if a user should be blocked
  • Login blocking in user-controller.ts:
    • Checks authenticated users in /login route handler
    • Redirects blocked users to app.ona.com/login
  • Workspace blocking in workspace-service-api.ts:
    • Blocks createAndStartWorkspace() operations
    • Blocks startWorkspace() operations
    • Returns permission denied error with redirect message

Frontend Changes

  • Login page (Login.tsx):
    • Shows "Login with Ona" button when sunset is enabled
    • Keeps SSO login form visible for exempted organizations
    • Updates heading to "Gitpod Classic has sunset"
    • Hides sunset notice banner when flag is enabled
  • Feature flag added to featureflag-query.ts

Feature Flag Configuration

  • Name: classic_payg_sunset_enabled
  • Type: JSON object
  • Structure: { enabled: boolean, exemptedOrganizations: string[] }
  • Default: { enabled: false, exemptedOrganizations: [] }

Exemption Logic

Users are NOT blocked if:

  • They have rolesOrPermissions (admins, staff)
  • Their organizationId is in the exemptedOrganizations list

Users ARE blocked if:

  • They are installation-owned users (no organizationId)
  • They belong to non-exempted organizations

Testing

Related Issues

Fixes CLC-2032

Implement feature flag-based blocking for Gitpod Classic PAYG users:

Backend:
- Add utility functions to check if user is blocked by sunset
- Block login attempts in /login route handler, redirect to app.ona.com
- Block workspace creation and start operations in workspace-service-api
- Exempt users with roles/permissions and users in exempted organizations

Frontend:
- Update login page to show 'Login with Ona' button when sunset is enabled
- Keep SSO login form visible for exempted organizations
- Hide sunset notice banner when flag is enabled
- Update heading to 'Gitpod Classic has sunset'

Feature flag: classic_payg_sunset_enabled (JSON with enabled boolean and exemptedOrganizations array)

Co-authored-by: Ona <[email protected]>
geropl and others added 9 commits October 15, 2025 06:08
When sunset is enabled on gitpod.io, users now see a simplified UI:
- 'Continue with Ona' button (default)
- Link to show all login options (?oldLogin=true)

With ?oldLogin=true parameter:
- Shows all OAuth provider buttons
- Shows SSO login form
- Full functionality for exempted organizations

The link preserves returnToPath parameter if present.

Co-authored-by: Ona <[email protected]>
Split sunset blocking logic into two functions:
- isUserLoginBlockedBySunset: checks roles/permissions exemption for login
- isWorkspaceStartBlockedBySunset: checks org-level exemption for workspace ops

Move ClassicPaygSunsetConfig interface to gitpod-protocol for reusability.
Pass organizationId explicitly to workspace blocking checks.

Co-authored-by: Ona <[email protected]>
Import ClassicPaygSunsetConfig type from gitpod-protocol and use it
as the default value for classic_payg_sunset_enabled feature flag.

This leverages TypeScript's generic type inference in useFeatureFlag:
- useFeatureFlag<K extends keyof FeatureFlags> returns FeatureFlags[K]
- For classic_payg_sunset_enabled, it now returns ClassicPaygSunsetConfig
- Other flags continue to return their respective types (boolean, string, etc.)

Updated Login.tsx to access .enabled property with type guard to handle
the union type (ClassicPaygSunsetConfig | boolean) during loading state.

This ensures type safety and consistency between frontend and backend.

Co-authored-by: Ona <[email protected]>
ConfigCat text flags return strings, so we need to parse JSON on both
frontend and backend.

Backend (featureflags.ts):
- Send JSON.stringify(defaultConfig) to ConfigCat
- Parse returned string with JSON.parse()
- Handle errors gracefully with fallback to default

Frontend (featureflag-query.ts):
- Add parseFeatureFlagValue() helper for JSON flags
- Send stringified default for classic_payg_sunset_enabled
- Parse returned string value
- Maintain type safety with generic return types

This allows ConfigCat to store the flag as text while maintaining
the typed object structure in our code.

Co-authored-by: Ona <[email protected]>
Add isDedicatedInstallation parameter to sunset check functions.
Dedicated installations always return false (not blocked) regardless
of feature flag state.

Changes:
- isUserLoginBlockedBySunset: add isDedicatedInstallation param
- isWorkspaceStartBlockedBySunset: add isDedicatedInstallation param
- UserController: pass config.isDedicatedInstallation to login check
- WorkspaceServiceAPI: inject Config and pass isDedicatedInstallation

This ensures the sunset only affects gitpod.io (PAYG) and not
dedicated installations.

Co-authored-by: Ona <[email protected]>
@corneliusludmann corneliusludmann marked this pull request as ready for review October 15, 2025 13:06
@corneliusludmann corneliusludmann requested a review from a team as a code owner October 15, 2025 13:06
@roboquat roboquat merged commit d42b06d into main Oct 15, 2025
34 checks passed
@roboquat roboquat deleted the clc-2032-classic-payg-sunset branch October 15, 2025 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants