mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 23:41:48 +01:00
docs: add canonical MONETIZATION.md and ENTITLEMENT_MATRIX.md (W1-C)
Single source of truth for tier → feature mapping. Confirms: - Basic SSO (OIDC) is free — matches features.go TierFree - Advanced SSO (SAML) is Pro — matches features.go TierPro - No upgrade reason exists for basic SSO (correct) - All 16 feature keys mapped across 6 tiers with code references
This commit is contained in:
66
MONETIZATION.md
Normal file
66
MONETIZATION.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Pulse Monetization (Self-Hosted + Hosted)
|
||||
|
||||
This document describes what Pulse sells and how feature entitlements map to license tiers.
|
||||
|
||||
Source of truth for runtime gating is `internal/license/features.go` (tier -> feature keys). If this file
|
||||
and any marketing/in-app copy disagree, the code wins and the copy must be updated.
|
||||
|
||||
## Tier Overview
|
||||
|
||||
Pulse uses capability keys (feature flags) to gate paid functionality. Some capabilities are additionally
|
||||
gated by non-license mechanisms (for example, AI autonomy level).
|
||||
|
||||
### Community (Free, Self-Hosted)
|
||||
|
||||
Included capabilities:
|
||||
- `ai_patrol` (Pulse Patrol runs on BYOK; advanced autonomy outcomes are separately gated)
|
||||
- `sso` (Basic SSO via OIDC)
|
||||
- `update_alerts`
|
||||
|
||||
Notes:
|
||||
- Basic SSO (OIDC) is free. Advanced SSO remains paid via `advanced_sso`.
|
||||
|
||||
### Pro Intelligence (Monthly / Annual / Lifetime)
|
||||
|
||||
Included capabilities:
|
||||
- `ai_patrol`
|
||||
- `ai_alerts`
|
||||
- `ai_autofix`
|
||||
- `kubernetes_ai`
|
||||
- `agent_profiles`
|
||||
- `update_alerts`
|
||||
- `relay`
|
||||
- `sso` (Basic OIDC)
|
||||
- `advanced_sso` (SAML, multi-provider, role mapping)
|
||||
- `rbac`
|
||||
- `audit_logging`
|
||||
- `advanced_reporting`
|
||||
- `long_term_metrics`
|
||||
|
||||
Notes:
|
||||
- Audit events may be captured regardless of tier, but access to query/export is gated behind `audit_logging`.
|
||||
- Long-range metrics history beyond the free window is gated by `long_term_metrics`.
|
||||
|
||||
### MSP
|
||||
|
||||
MSP includes all Pro capabilities plus:
|
||||
- `unlimited` (volume/instance limit removal)
|
||||
|
||||
Notes:
|
||||
- `multi_user` and `white_label` exist as capability keys but are not currently included in the MSP tier in code.
|
||||
|
||||
### Enterprise
|
||||
|
||||
Enterprise includes all Pro capabilities plus:
|
||||
- `unlimited`
|
||||
- `multi_user`
|
||||
- `white_label`
|
||||
- `multi_tenant`
|
||||
|
||||
Notes:
|
||||
- Multi-tenant is also guarded by a feature flag (`PULSE_MULTI_TENANT_ENABLED=true`) in addition to licensing.
|
||||
|
||||
## Capability Keys
|
||||
|
||||
Canonical list and tier mapping lives in `docs/architecture/ENTITLEMENT_MATRIX.md`.
|
||||
|
||||
50
docs/architecture/ENTITLEMENT_MATRIX.md
Normal file
50
docs/architecture/ENTITLEMENT_MATRIX.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Entitlement Matrix (Canonical)
|
||||
|
||||
This document is the canonical, single source of truth for feature entitlements by tier.
|
||||
|
||||
If this document disagrees with runtime enforcement, update this document *and* fix the code to match
|
||||
`internal/license/features.go` (tier -> capability keys). Keep them aligned.
|
||||
|
||||
## Source Of Truth
|
||||
|
||||
- Capability keys and tier mapping: `internal/license/features.go` (see `TierFeatures`, starting at line 52).
|
||||
- Display names: `internal/license/features.go` (see `GetFeatureDisplayName`, starting at line 210).
|
||||
- Runtime checks: primarily `license.Service.HasFeature()` / `RequireFeature()` and API middleware wrappers such as
|
||||
`internal/api/license_handlers.go:RequireLicenseFeature`.
|
||||
|
||||
## Tiers
|
||||
|
||||
Pulse tiers in code:
|
||||
- `free`
|
||||
- `pro`
|
||||
- `pro_annual`
|
||||
- `lifetime`
|
||||
- `msp`
|
||||
- `enterprise`
|
||||
|
||||
## Matrix
|
||||
|
||||
Legend:
|
||||
- Included in tier: `Y` / `N` (derived from `TierFeatures` in `internal/license/features.go`).
|
||||
- Feature definition line: where the capability key is declared in `internal/license/features.go`.
|
||||
|
||||
| Constant | Key | Display Name | Feature Line | free | pro | pro_annual | lifetime | msp | enterprise | Primary Gating Mechanism / Notes |
|
||||
|---|---|---|---:|:---:|:---:|:---:|:---:|:---:|:---:|---|
|
||||
| `FeatureAIPatrol` | `ai_patrol` | Pulse Patrol (Background Health Checks) | 10 | Y | Y | Y | Y | Y | Y | Patrol itself is available on Free (BYOK). Higher autonomy outcomes and fix execution are separately gated; auto-fix and some mutation endpoints require `ai_autofix` (see API routing in `internal/api/router_routes_ai_relay.go`). |
|
||||
| `FeatureAIAlerts` | `ai_alerts` | Alert Analysis | 11 | N | Y | Y | Y | Y | Y | API route gating via `RequireLicenseFeature(..., ai_alerts, ...)` (for example `/api/ai/investigate-alert` in `internal/api/router_routes_ai_relay.go`). |
|
||||
| `FeatureAIAutoFix` | `ai_autofix` | Pulse Patrol Auto-Fix | 12 | N | Y | Y | Y | Y | Y | Required for fix execution and higher-autonomy actions; enforced via `RequireLicenseFeature` in AI routes (for example `/api/ai/findings/.../reapprove`). |
|
||||
| `FeatureKubernetesAI` | `kubernetes_ai` | Kubernetes Analysis | 13 | N | Y | Y | Y | Y | Y | API route gating via `RequireLicenseFeature(..., kubernetes_ai, ...)` (for example `/api/ai/kubernetes/analyze`). |
|
||||
| `FeatureAgentProfiles` | `agent_profiles` | Centralized Agent Profiles | 16 | N | Y | Y | Y | Y | Y | API route gating via `RequireLicenseFeature(..., agent_profiles, ...)` (for example `/api/admin/profiles/` in `internal/api/router_routes_registration.go`). |
|
||||
| `FeatureUpdateAlerts` | `update_alerts` | Update Alerts (Container/Package Updates) | 19 | Y | Y | Y | Y | Y | Y | Capability exists and is exposed on license status; feature-specific enforcement is implementation-dependent. Included in Free tier per `TierFeatures[TierFree]`. |
|
||||
| `FeatureRBAC` | `rbac` | Role-Based Access Control (RBAC) | 22 | N | Y | Y | Y | Y | Y | API route gating via `RequireLicenseFeature(..., rbac, ...)` for RBAC endpoints (see `internal/api/router_routes_org_license.go`). |
|
||||
| `FeatureAuditLogging` | `audit_logging` | Enterprise Audit Logging | 23 | N | Y | Y | Y | Y | Y | API route gating for audit query/verify/export endpoints via `RequireLicenseFeature(..., audit_logging, ...)` (see `internal/api/router_routes_org_license.go`). |
|
||||
| `FeatureSSO` | `sso` | Basic SSO (OIDC) | 24 | Y | Y | Y | Y | Y | Y | Basic SSO (OIDC) is included in Free tier. Advanced SSO functionality is separately paid via `advanced_sso`. |
|
||||
| `FeatureAdvancedSSO` | `advanced_sso` | Advanced SSO (SAML/Multi-Provider) | 25 | N | Y | Y | Y | Y | Y | Used to gate advanced SSO capabilities such as SAML and multi-provider flows. Frontend currently uses `advanced_sso` to show Advanced SSO UI (see `frontend-modern/src/components/Settings/SSOProvidersPanel.tsx`). |
|
||||
| `FeatureAdvancedReporting` | `advanced_reporting` | Advanced Infrastructure Reporting (PDF/CSV) | 26 | N | Y | Y | Y | Y | Y | API route gating via `RequireLicenseFeature(..., advanced_reporting, ...)` for report generation endpoints (see `internal/api/router_routes_org_license.go`). |
|
||||
| `FeatureLongTermMetrics` | `long_term_metrics` | 90-Day Metric History | 27 | N | Y | Y | Y | Y | Y | Used to gate long-range history queries; for example, history durations beyond 7 days are blocked without `long_term_metrics` (see `internal/api/router.go` around the history handler). |
|
||||
| `FeatureRelay` | `relay` | Remote Access (Mobile Relay) | 30 | N | Y | Y | Y | Y | Y | API route gating via `RequireLicenseFeature(..., relay, ...)` for relay settings endpoints (see `internal/api/router_routes_ai_relay.go`). |
|
||||
| `FeatureMultiUser` | `multi_user` | Multi-User Mode | 33 | N | N | N | N | N | Y | Capability key exists for Enterprise-only multi-user mode; current API surface may additionally rely on `rbac` for day-to-day role/user operations. |
|
||||
| `FeatureWhiteLabel` | `white_label` | White-Label Branding | 34 | N | N | N | N | N | Y | Capability key exists; marked as not implemented in `internal/license/features.go`. |
|
||||
| `FeatureMultiTenant` | `multi_tenant` | Multi-Tenant Mode | 35 | N | N | N | N | N | Y | Requires both a feature flag (`PULSE_MULTI_TENANT_ENABLED=true`) and the `multi_tenant` capability for non-default orgs (see `internal/api/middleware_license.go`). |
|
||||
| `FeatureUnlimited` | `unlimited` | Unlimited Instances | 36 | N | N | N | N | Y | Y | Used for volume/instance limit removal (MSP/Enterprise); enforcement is limit-check dependent. |
|
||||
|
||||
@@ -89,7 +89,7 @@ func resourceFromHost(host models.Host) (Resource, ResourceIdentity) {
|
||||
}
|
||||
|
||||
// Populate sensors
|
||||
if len(host.Sensors.TemperatureCelsius) > 0 || len(host.Sensors.FanRPM) > 0 || len(host.Sensors.SMART) > 0 {
|
||||
if len(host.Sensors.TemperatureCelsius) > 0 || len(host.Sensors.FanRPM) > 0 || len(host.Sensors.Additional) > 0 || len(host.Sensors.SMART) > 0 {
|
||||
sensorMeta := &HostSensorMeta{}
|
||||
if len(host.Sensors.TemperatureCelsius) > 0 {
|
||||
sensorMeta.TemperatureCelsius = make(map[string]float64, len(host.Sensors.TemperatureCelsius))
|
||||
@@ -103,6 +103,12 @@ func resourceFromHost(host models.Host) (Resource, ResourceIdentity) {
|
||||
sensorMeta.FanRPM[k] = v
|
||||
}
|
||||
}
|
||||
if len(host.Sensors.Additional) > 0 {
|
||||
sensorMeta.Additional = make(map[string]float64, len(host.Sensors.Additional))
|
||||
for k, v := range host.Sensors.Additional {
|
||||
sensorMeta.Additional[k] = v
|
||||
}
|
||||
}
|
||||
if len(host.Sensors.SMART) > 0 {
|
||||
sensorMeta.SMART = make([]HostSMARTMeta, len(host.Sensors.SMART))
|
||||
for i, s := range host.Sensors.SMART {
|
||||
|
||||
@@ -252,6 +252,7 @@ type SMARTMeta struct {
|
||||
type HostSensorMeta struct {
|
||||
TemperatureCelsius map[string]float64 `json:"temperatureCelsius,omitempty"`
|
||||
FanRPM map[string]float64 `json:"fanRpm,omitempty"`
|
||||
Additional map[string]float64 `json:"additional,omitempty"`
|
||||
SMART []HostSMARTMeta `json:"smart,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user