feat(codersdk): revert "remove AI Bridge entitlement from Premium license" (#21653)

Reverts coder/coder#21540
This commit is contained in:
Kacper Sawicki
2026-01-23 15:58:12 +00:00
committed by GitHub
parent f5858c8a18
commit b82693d4cc
4 changed files with 10 additions and 46 deletions
+4 -4
View File
@@ -170,8 +170,7 @@ func (n FeatureName) AlwaysEnable() bool {
func (n FeatureName) Enterprise() bool {
switch n {
// Add all features that should be excluded in the Enterprise feature set.
// AI Bridge is a separate add-on.
case FeatureMultipleOrganizations, FeatureCustomRoles, FeatureAIBridge:
case FeatureMultipleOrganizations, FeatureCustomRoles:
return false
default:
return true
@@ -225,10 +224,11 @@ func (set FeatureSet) Features() []FeatureName {
case FeatureSetPremium:
premiumFeatures := make([]FeatureName, len(FeatureNames))
copy(premiumFeatures, FeatureNames)
// Remove features that use limits and AI Bridge (now a separate add-on).
// Remove the selection
premiumFeatures = slices.DeleteFunc(premiumFeatures, func(f FeatureName) bool {
return f.UsesLimit() || f == FeatureAIBridge
return f.UsesLimit()
})
// FeatureSetPremium is just all features.
return premiumFeatures
}
// By default, return an empty set.
+3 -3
View File
@@ -623,16 +623,16 @@ func TestPremiumSuperSet(t *testing.T) {
// Premium ⊃ Enterprise
require.Subset(t, premium.Features(), enterprise.Features(), "premium should be a superset of enterprise. If this fails, update the premium feature set to include all enterprise features.")
// Premium = All Features EXCEPT usage limit features and AI Bridge (add-on).
// Premium = All Features EXCEPT usage limit features
expectedPremiumFeatures := []codersdk.FeatureName{}
for _, feature := range codersdk.FeatureNames {
if feature.UsesLimit() || feature == codersdk.FeatureAIBridge {
if feature.UsesLimit() {
continue
}
expectedPremiumFeatures = append(expectedPremiumFeatures, feature)
}
require.NotEmpty(t, expectedPremiumFeatures, "expectedPremiumFeatures should not be empty")
require.ElementsMatch(t, premium.Features(), expectedPremiumFeatures, "premium should contain all features except usage limit features and AI Bridge")
require.ElementsMatch(t, premium.Features(), expectedPremiumFeatures, "premium should contain all features except usage limit features")
// This check exists because if you misuse the slices.Delete, you can end up
// with zero'd values.
-13
View File
@@ -548,15 +548,6 @@ func LicensesEntitlements(
featureArguments.ActiveUserCount, *userLimit.Limit))
}
// AI Bridge has a custom warning message as it moved to a separate add-on.
aiBridge := entitlements.Features[codersdk.FeatureAIBridge]
if aiBridge.Enabled && aiBridge.Entitlement != codersdk.EntitlementEntitled {
entitlements.Warnings = append(entitlements.Warnings,
"AI Bridge has reached General Availability and your Coder deployment is not entitled "+
"to run this feature. Contact your account team (https://coder.com/contact) for "+
"information around getting a license with AI Bridge.")
}
// Add a warning for every feature that is enabled but not entitled or
// is in a grace period.
for _, featureName := range codersdk.FeatureNames {
@@ -576,10 +567,6 @@ func LicensesEntitlements(
if featureName == codersdk.FeatureManagedAgentLimit {
continue
}
// AI Bridge has a custom warning message as it moved to a separate add-on.
if featureName == codersdk.FeatureAIBridge {
continue
}
feature := entitlements.Features[featureName]
if !feature.Enabled {
+3 -26
View File
@@ -25,10 +25,6 @@ func TestEntitlements(t *testing.T) {
t.Parallel()
all := make(map[codersdk.FeatureName]bool)
for _, n := range codersdk.FeatureNames {
// AI Bridge is a separate add-on, not included in standard feature sets.
if n == codersdk.FeatureAIBridge {
continue
}
all[n] = true
}
@@ -370,9 +366,9 @@ func TestEntitlements(t *testing.T) {
require.True(t, entitlements.HasLicense)
require.False(t, entitlements.Trial)
for _, featureName := range codersdk.FeatureNames {
if featureName == codersdk.FeatureUserLimit || featureName == codersdk.FeatureHighAvailability || featureName == codersdk.FeatureMultipleExternalAuth || featureName == codersdk.FeatureManagedAgentLimit || featureName == codersdk.FeatureAIBridge {
if featureName == codersdk.FeatureUserLimit || featureName == codersdk.FeatureHighAvailability || featureName == codersdk.FeatureMultipleExternalAuth || featureName == codersdk.FeatureManagedAgentLimit {
// These fields don't generate warnings when not entitled unless
// a limit is breached, or have custom warning messages.
// a limit is breached.
continue
}
niceName := featureName.Humanize()
@@ -802,25 +798,6 @@ func TestEntitlements(t *testing.T) {
require.Equal(t, "You have multiple External Auth Providers configured but your license is expired. Reduce to one.", entitlements.Warnings[0])
})
t.Run("AIBridgeEnabledNotEntitled", func(t *testing.T) {
t.Parallel()
db, _ := dbtestutil.NewDB(t)
db.InsertLicense(context.Background(), database.InsertLicenseParams{
Exp: time.Now().Add(time.Hour),
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureAuditLog: 1, // Some feature but not AI Bridge.
},
}),
})
entitlements, err := license.Entitlements(context.Background(), db, 1, 1, coderdenttest.Keys, map[codersdk.FeatureName]bool{
codersdk.FeatureAIBridge: true, // Enabled but not entitled.
})
require.NoError(t, err)
require.True(t, entitlements.HasLicense)
require.Contains(t, entitlements.Warnings, "AI Bridge has reached General Availability and your Coder deployment is not entitled to run this feature. Contact your account team (https://coder.com/contact) for information around getting a license with AI Bridge.")
})
t.Run("ManagedAgentLimitHasValue", func(t *testing.T) {
t.Parallel()
@@ -915,7 +892,7 @@ func TestLicenseEntitlements(t *testing.T) {
codersdk.FeatureAccessControl: true,
codersdk.FeatureControlSharedPorts: true,
codersdk.FeatureWorkspaceExternalAgent: true,
// FeatureAIBridge is intentionally not included as it's a separate add-on.
codersdk.FeatureAIBridge: true,
}
legacyLicense := func() *coderdenttest.LicenseOptions {