mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 02:25:56 +00:00
Exclude placeholder capabilities from dev entitlements
This commit is contained in:
@@ -325,6 +325,11 @@ That widening still has to respect runtime feature flags. A capability like
|
||||
`multi_tenant` must stay absent from dev/demo entitlement payloads until the
|
||||
process also has `PULSE_MULTI_TENANT_ENABLED=true`; otherwise admin shells
|
||||
drift into impossible routes that the same backend still rejects as disabled.
|
||||
The same rule applies to placeholder or plan-marker capabilities as well:
|
||||
dev/demo entitlement payloads must not advertise non-operable entries like
|
||||
`white_label`, `multi_user`, or `unlimited` just because they exist in tier
|
||||
metadata, when the current runtime does not expose a corresponding usable
|
||||
feature surface.
|
||||
The `/api/resources` serializer now also refreshes canonical identity and
|
||||
policy metadata through the shared unified-resource helper before it writes
|
||||
the payload, so backend and frontend contract tests stay aligned on one
|
||||
|
||||
@@ -692,6 +692,11 @@ That dev widening is still bounded by runtime readiness rather than marketing
|
||||
intent: `multi_tenant` is not a valid advertised dev capability unless the
|
||||
process also has `PULSE_MULTI_TENANT_ENABLED=true`, because the org API surface
|
||||
is intentionally disabled otherwise.
|
||||
The same runtime-readiness rule also excludes placeholder and plan-marker
|
||||
entries like `white_label`, `multi_user`, and `unlimited` from dev/demo
|
||||
entitlement payloads when there is no corresponding operable runtime surface;
|
||||
those belong in tier metadata and plan semantics, not in live capability
|
||||
advertising for a free dev shell.
|
||||
Cloud/MSP live price IDs are no longer an open fill-in task either. The audit
|
||||
record `docs/release-control/v6/records/cloud-msp-price-audit-2026-03-13.md`
|
||||
verified that the 13 canonical Cloud/MSP v6 `price_*` IDs are present in the
|
||||
|
||||
@@ -390,6 +390,15 @@ func TestEntitlementHandler_DevModeMirrorsFeatureGateCapabilities(t *testing.T)
|
||||
if containsCapability(payload.Capabilities, license.FeatureMultiTenant) {
|
||||
t.Fatalf("expected dev entitlements to omit %q while runtime flag is disabled, got %v", license.FeatureMultiTenant, payload.Capabilities)
|
||||
}
|
||||
for _, feature := range []string{
|
||||
license.FeatureMultiUser,
|
||||
license.FeatureWhiteLabel,
|
||||
license.FeatureUnlimited,
|
||||
} {
|
||||
if containsCapability(payload.Capabilities, feature) {
|
||||
t.Fatalf("expected dev entitlements to omit non-runtime capability %q, got %v", feature, payload.Capabilities)
|
||||
}
|
||||
}
|
||||
if len(payload.UpgradeReasons) != 0 {
|
||||
t.Fatalf("expected no upgrade reasons in dev mode, got %v", payload.UpgradeReasons)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ func devModeFeatures() []string {
|
||||
|
||||
func devModeFeatureEnabled(feature string) bool {
|
||||
switch feature {
|
||||
case FeatureMultiUser, FeatureWhiteLabel, FeatureUnlimited:
|
||||
return false
|
||||
case FeatureMultiTenant:
|
||||
return strings.EqualFold(strings.TrimSpace(os.Getenv("PULSE_MULTI_TENANT_ENABLED")), "true")
|
||||
default:
|
||||
|
||||
@@ -194,6 +194,14 @@ func TestServiceStatus_DevModeAdvertisesOnlyRuntimeEnabledFeaturesWithoutLicense
|
||||
if containsStringValue(status.Features, FeatureMultiTenant) {
|
||||
t.Fatalf("status.Features unexpectedly includes %q when runtime flag is disabled: %v", FeatureMultiTenant, status.Features)
|
||||
}
|
||||
for _, feature := range []string{FeatureMultiUser, FeatureWhiteLabel, FeatureUnlimited} {
|
||||
if svc.HasFeature(feature) {
|
||||
t.Fatalf("HasFeature(%q)=true, want false for non-runtime dev capability", feature)
|
||||
}
|
||||
if containsStringValue(status.Features, feature) {
|
||||
t.Fatalf("status.Features unexpectedly includes %q in dev mode: %v", feature, status.Features)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceStatus_DevModeIncludesMultiTenantWhenRuntimeEnabled(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user