mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-09 16:00:59 +00:00
Manifest-backed MCP tools, prompts, and resources with surface affordance contracts; agent capability manifest and governance projection; API contract tests and capability route projection; operations-loop and intelligence-funnel telemetry; release-control subsystem documentation, registry, and tooling; licensing and configuration.
371 lines
12 KiB
Go
371 lines
12 KiB
Go
package licensing
|
|
|
|
import "sort"
|
|
|
|
type SelfHostedFeatureRole string
|
|
|
|
const (
|
|
SelfHostedFeatureRoleHidden SelfHostedFeatureRole = "hidden"
|
|
SelfHostedFeatureRoleIncluded SelfHostedFeatureRole = "included"
|
|
SelfHostedFeatureRolePrimaryPillar SelfHostedFeatureRole = "primary_pillar"
|
|
SelfHostedFeatureRoleIncludedExtra SelfHostedFeatureRole = "included_extra"
|
|
SelfHostedFeatureRoleCompatibilityOnly SelfHostedFeatureRole = "compatibility_only"
|
|
)
|
|
|
|
type SelfHostedFeatureRoles struct {
|
|
Community SelfHostedFeatureRole
|
|
Relay SelfHostedFeatureRole
|
|
Pro SelfHostedFeatureRole
|
|
}
|
|
|
|
type FeatureMetadata struct {
|
|
Key string
|
|
DisplayName string
|
|
ComparisonName string
|
|
ShowInComparisonTable bool
|
|
DisplayableInPlanUI bool
|
|
SelfHostedRoles SelfHostedFeatureRoles
|
|
UpgradeReason string
|
|
UpgradePriority int
|
|
}
|
|
|
|
var orderedFeatureMetadataKeys = []string{
|
|
FeatureUpdateAlerts,
|
|
FeatureSSO,
|
|
FeatureAIPatrol,
|
|
FeatureRelay,
|
|
FeatureMobileApp,
|
|
FeaturePushNotifications,
|
|
FeatureAIAlerts,
|
|
FeatureAIAutoFix,
|
|
FeatureLongTermMetrics,
|
|
FeatureAdvancedSSO,
|
|
FeatureRBAC,
|
|
FeatureAuditLogging,
|
|
FeatureAdvancedReporting,
|
|
FeatureAgentProfiles,
|
|
FeatureKubernetesAI,
|
|
FeatureMultiUser,
|
|
FeatureWhiteLabel,
|
|
FeatureMultiTenant,
|
|
FeatureUnlimited,
|
|
FeatureDemoFixtures,
|
|
}
|
|
|
|
var featureMetadataCatalog = map[string]FeatureMetadata{
|
|
FeatureUpdateAlerts: {
|
|
Key: FeatureUpdateAlerts,
|
|
DisplayName: "Update Alerts (Container/Package Updates)",
|
|
ComparisonName: "Update Alerts",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleIncluded,
|
|
Relay: SelfHostedFeatureRoleIncluded,
|
|
Pro: SelfHostedFeatureRoleIncluded,
|
|
},
|
|
},
|
|
FeatureSSO: {
|
|
Key: FeatureSSO,
|
|
DisplayName: "Core SSO (OIDC/SAML)",
|
|
ComparisonName: "Core SSO (OIDC/SAML)",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleIncluded,
|
|
Relay: SelfHostedFeatureRoleIncluded,
|
|
Pro: SelfHostedFeatureRoleIncluded,
|
|
},
|
|
},
|
|
FeatureAIPatrol: {
|
|
Key: FeatureAIPatrol,
|
|
DisplayName: "Pulse Patrol (Background Health Checks)",
|
|
ComparisonName: "Pulse Patrol",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleIncluded,
|
|
Relay: SelfHostedFeatureRoleIncluded,
|
|
Pro: SelfHostedFeatureRoleIncluded,
|
|
},
|
|
},
|
|
FeatureRelay: {
|
|
Key: FeatureRelay,
|
|
DisplayName: "Pulse Relay (Remote Access)",
|
|
ComparisonName: "Pulse Relay (Remote Access)",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRolePrimaryPillar,
|
|
Pro: SelfHostedFeatureRoleIncluded,
|
|
},
|
|
UpgradeReason: "Get Relay so Pulse stays reachable securely from anywhere instead of only on the local dashboard.",
|
|
UpgradePriority: 1,
|
|
},
|
|
FeatureMobileApp: {
|
|
Key: FeatureMobileApp,
|
|
DisplayName: "Pulse Mobile Pairing",
|
|
ComparisonName: "Pulse Mobile Pairing",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRolePrimaryPillar,
|
|
Pro: SelfHostedFeatureRoleIncluded,
|
|
},
|
|
UpgradeReason: "Get Relay so Pulse Mobile can pair with this instance for secure handoff and notifications.",
|
|
UpgradePriority: 1,
|
|
},
|
|
FeaturePushNotifications: {
|
|
Key: FeaturePushNotifications,
|
|
DisplayName: "Push Notifications",
|
|
ComparisonName: "Push Notifications",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRolePrimaryPillar,
|
|
Pro: SelfHostedFeatureRoleIncluded,
|
|
},
|
|
UpgradeReason: "Get Relay so important alerts reach you immediately on mobile instead of waiting for you to reopen Pulse.",
|
|
UpgradePriority: 1,
|
|
},
|
|
FeatureLongTermMetrics: {
|
|
Key: FeatureLongTermMetrics,
|
|
DisplayName: "Extended Metric History",
|
|
ComparisonName: "Extended Metric History",
|
|
ShowInComparisonTable: false,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRolePrimaryPillar,
|
|
Pro: SelfHostedFeatureRolePrimaryPillar,
|
|
},
|
|
UpgradeReason: "Get Relay for 14 days of history, or Pro for 90 days, so you can see what changed before and after an incident.",
|
|
UpgradePriority: 2,
|
|
},
|
|
FeatureAIAlerts: {
|
|
Key: FeatureAIAlerts,
|
|
DisplayName: "Patrol Investigates Issues",
|
|
ComparisonName: "Patrol Investigates Issues",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRolePrimaryPillar,
|
|
},
|
|
UpgradeReason: "Upgrade to Pro so Patrol can investigate issues instead of handing you a stack of symptoms.",
|
|
UpgradePriority: 4,
|
|
},
|
|
FeatureAIAutoFix: {
|
|
Key: FeatureAIAutoFix,
|
|
DisplayName: "Patrol Handles Safe Fixes",
|
|
ComparisonName: "Patrol Handles Safe Fixes",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRolePrimaryPillar,
|
|
},
|
|
UpgradeReason: "Upgrade to Pro so Patrol can investigate issues, handle safe fixes within Patrol mode, and verify the outcome.",
|
|
UpgradePriority: 3,
|
|
},
|
|
FeatureKubernetesAI: {
|
|
Key: FeatureKubernetesAI,
|
|
DisplayName: "Kubernetes AI Analysis (Compatibility)",
|
|
ComparisonName: "Kubernetes AI Analysis (Compatibility)",
|
|
ShowInComparisonTable: false,
|
|
DisplayableInPlanUI: false,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleCompatibilityOnly,
|
|
},
|
|
},
|
|
FeatureAgentProfiles: {
|
|
Key: FeatureAgentProfiles,
|
|
DisplayName: "Centralized Agent Profiles",
|
|
ComparisonName: "Centralized Agent Profiles",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleIncludedExtra,
|
|
},
|
|
UpgradeReason: "Upgrade to Pro to standardize agent behavior across systems without reconfiguring every install by hand.",
|
|
UpgradePriority: 6,
|
|
},
|
|
FeatureRBAC: {
|
|
Key: FeatureRBAC,
|
|
DisplayName: "Role-Based Access Control (RBAC)",
|
|
ComparisonName: "Role-Based Access Control (RBAC)",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleIncludedExtra,
|
|
},
|
|
UpgradeReason: "Upgrade to Pro when more than one operator needs safe access boundaries around infrastructure changes.",
|
|
UpgradePriority: 5,
|
|
},
|
|
FeatureAuditLogging: {
|
|
Key: FeatureAuditLogging,
|
|
DisplayName: "Audit Logging",
|
|
ComparisonName: "Audit Logging",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleIncludedExtra,
|
|
},
|
|
UpgradeReason: "Upgrade to Pro to keep a trustworthy action trail for incident review, accountability, and compliance.",
|
|
UpgradePriority: 8,
|
|
},
|
|
FeatureAdvancedSSO: {
|
|
Key: FeatureAdvancedSSO,
|
|
DisplayName: "Multi-Provider SSO",
|
|
ComparisonName: "Multi-Provider SSO",
|
|
ShowInComparisonTable: false,
|
|
DisplayableInPlanUI: false,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleIncluded,
|
|
Relay: SelfHostedFeatureRoleIncluded,
|
|
Pro: SelfHostedFeatureRoleIncluded,
|
|
},
|
|
},
|
|
FeatureAdvancedReporting: {
|
|
Key: FeatureAdvancedReporting,
|
|
DisplayName: "PDF/CSV Reporting",
|
|
ComparisonName: "PDF/CSV Reporting",
|
|
ShowInComparisonTable: true,
|
|
DisplayableInPlanUI: true,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleIncludedExtra,
|
|
},
|
|
UpgradeReason: "Upgrade to Pro to turn live infrastructure state into shareable reports without manual screenshot work.",
|
|
UpgradePriority: 9,
|
|
},
|
|
FeatureMultiUser: {
|
|
Key: FeatureMultiUser,
|
|
DisplayName: "Multi-User Mode",
|
|
ComparisonName: "Multi-User Mode",
|
|
DisplayableInPlanUI: false,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleHidden,
|
|
},
|
|
},
|
|
FeatureWhiteLabel: {
|
|
Key: FeatureWhiteLabel,
|
|
DisplayName: "White-Label Branding",
|
|
ComparisonName: "White-Label Branding",
|
|
DisplayableInPlanUI: false,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleHidden,
|
|
},
|
|
},
|
|
FeatureMultiTenant: {
|
|
Key: FeatureMultiTenant,
|
|
DisplayName: "Multi-Tenant Mode",
|
|
ComparisonName: "Multi-Tenant Mode",
|
|
DisplayableInPlanUI: false,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleHidden,
|
|
},
|
|
},
|
|
FeatureUnlimited: {
|
|
Key: FeatureUnlimited,
|
|
DisplayName: "Hosted Capacity Policy",
|
|
ComparisonName: "Hosted Capacity Policy",
|
|
DisplayableInPlanUI: false,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleHidden,
|
|
},
|
|
},
|
|
FeatureDemoFixtures: {
|
|
Key: FeatureDemoFixtures,
|
|
DisplayName: "Demo Fixtures (Internal)",
|
|
ComparisonName: "Demo Fixtures (Internal)",
|
|
DisplayableInPlanUI: false,
|
|
SelfHostedRoles: SelfHostedFeatureRoles{
|
|
Community: SelfHostedFeatureRoleHidden,
|
|
Relay: SelfHostedFeatureRoleHidden,
|
|
Pro: SelfHostedFeatureRoleHidden,
|
|
},
|
|
},
|
|
}
|
|
|
|
func AllFeatureMetadata() []FeatureMetadata {
|
|
metadata := make([]FeatureMetadata, 0, len(orderedFeatureMetadataKeys))
|
|
for _, key := range orderedFeatureMetadataKeys {
|
|
entry, ok := featureMetadataCatalog[key]
|
|
if !ok {
|
|
continue
|
|
}
|
|
metadata = append(metadata, entry)
|
|
}
|
|
return metadata
|
|
}
|
|
|
|
func GetFeatureMetadata(feature string) (FeatureMetadata, bool) {
|
|
entry, ok := featureMetadataCatalog[feature]
|
|
return entry, ok
|
|
}
|
|
|
|
func GetSelfHostedFeatureRole(feature string, tier Tier) SelfHostedFeatureRole {
|
|
entry, ok := featureMetadataCatalog[feature]
|
|
if !ok {
|
|
return SelfHostedFeatureRoleHidden
|
|
}
|
|
switch tier {
|
|
case TierFree:
|
|
return entry.SelfHostedRoles.Community
|
|
case TierRelay:
|
|
return entry.SelfHostedRoles.Relay
|
|
case TierPro, TierProPlus, TierProAnnual, TierLifetime:
|
|
return entry.SelfHostedRoles.Pro
|
|
default:
|
|
return SelfHostedFeatureRoleHidden
|
|
}
|
|
}
|
|
|
|
func IsCompatibilityOnlyFeature(feature string) bool {
|
|
entry, ok := featureMetadataCatalog[feature]
|
|
if !ok {
|
|
return false
|
|
}
|
|
return entry.SelfHostedRoles.Community == SelfHostedFeatureRoleCompatibilityOnly ||
|
|
entry.SelfHostedRoles.Relay == SelfHostedFeatureRoleCompatibilityOnly ||
|
|
entry.SelfHostedRoles.Pro == SelfHostedFeatureRoleCompatibilityOnly
|
|
}
|
|
|
|
func GenericUpgradeFeatureMetadata() []FeatureMetadata {
|
|
out := make([]FeatureMetadata, 0)
|
|
for _, entry := range AllFeatureMetadata() {
|
|
if entry.UpgradeReason != "" {
|
|
out = append(out, entry)
|
|
}
|
|
}
|
|
sort.SliceStable(out, func(i, j int) bool {
|
|
if out[i].UpgradePriority == out[j].UpgradePriority {
|
|
return out[i].Key < out[j].Key
|
|
}
|
|
return out[i].UpgradePriority < out[j].UpgradePriority
|
|
})
|
|
return out
|
|
}
|