Pulse/docs/PULSE_PRO_IMPLEMENTATION.md
rcourtman ae70d9e423 feat: add --kube-include-all-deployments flag for Kubernetes agent
Adds IncludeAllDeployments option to show all deployments, not just
problem ones (where replicas don't match desired). This provides parity
with the existing --kube-include-all-pods flag.

- Add IncludeAllDeployments to kubernetesagent.Config
- Add --kube-include-all-deployments flag and PULSE_KUBE_INCLUDE_ALL_DEPLOYMENTS env var
- Update collectDeployments to respect the new flag
- Add test for IncludeAllDeployments functionality
- Update UNIFIED_AGENT.md documentation

Addresses feedback from PR #855
2025-12-18 20:58:30 +00:00

401 lines
14 KiB
Markdown

# Pulse Pro Implementation Plan
**Goal**: Gate AI features behind a Pro license to create a sustainable income stream.
**Timeline**: ~1-2 weeks of focused work
---
## Phase 1: License System Architecture
### 1.1 License Format (Simple JWT)
```go
// internal/license/license.go
type LicenseData struct {
LicenseID string `json:"lid"` // Unique license ID
Email string `json:"email"` // Customer email
Tier string `json:"tier"` // "pro", "msp", "enterprise"
IssuedAt time.Time `json:"iat"`
ExpiresAt time.Time `json:"exp"` // Empty = lifetime
MaxNodes int `json:"max_nodes"` // 0 = unlimited
Features []string `json:"features"` // ["ai_chat", "ai_patrol", "ai_alerts"]
}
```
**Why JWT?**
- Self-contained (no license server needed for validation)
- Signed with your private key, verified with public key embedded in binary
- Can be verified offline (important for air-gapped homelabs)
- Standard format, easy to generate from any payment processor webhook
### 1.2 License Validation Flow
```
┌────────────────────────────────────────────────────────────────┐
│ User purchases license on LemonSqueezy/Gumroad │
│ ↓ │
│ Webhook hits your simple license API (can be CloudFlare Worker)│
│ ↓ │
│ Generate JWT signed with private key │
│ ↓ │
│ Email license key to customer │
│ ↓ │
│ User pastes key in Pulse Settings → Pro tab │
│ ↓ │
│ Pulse validates signature with embedded public key │
│ ↓ │
│ Store encrypted license in config dir (license.enc) │
└────────────────────────────────────────────────────────────────┘
```
---
## Phase 2: Backend Implementation
### 2.1 New Files to Create
```
internal/license/
├── license.go # License struct, validation, JWT parsing
├── license_test.go # Tests
└── features.go # Feature flags (what Pro includes)
internal/config/
└── license.go # License persistence (store/load from disk)
```
### 2.2 License Service
```go
// internal/license/license.go
package license
import (
"crypto/ed25519"
"encoding/base64"
"errors"
"time"
"github.com/golang-jwt/jwt/v5"
)
// Embedded public key (compiled into binary)
// Generate keypair: go run ./cmd/license-keygen
var publicKeyBase64 = "YOUR_PUBLIC_KEY_HERE"
type Service struct {
license *LicenseData
loaded bool
}
func NewService() *Service {
return &Service{}
}
func (s *Service) LoadFromKey(licenseKey string) error {
// Parse and validate JWT
// Store in s.license
}
func (s *Service) IsValid() bool {
if s.license == nil {
return false
}
if !s.license.ExpiresAt.IsZero() && time.Now().After(s.license.ExpiresAt) {
return false
}
return true
}
func (s *Service) HasFeature(feature string) bool {
if !s.IsValid() {
return false
}
for _, f := range s.license.Features {
if f == feature || f == "all" {
return true
}
}
return false
}
// Feature constants
const (
FeatureAIChat = "ai_chat"
FeatureAIPatrol = "ai_patrol"
FeatureAIAlerts = "ai_alerts"
FeatureOIDC = "oidc" // SSO/OIDC authentication
FeatureKubernetes = "kubernetes" // K8s cluster monitoring
FeatureMultiUser = "multi_user" // Multiple user accounts
FeatureAPIAccess = "api_access" // Full API access for integrations
FeatureWhiteLabel = "white_label" // Custom branding (MSP tier)
FeatureAll = "all"
)
```
### 2.3 Integration Points
Modify these files to check license:
| File | What to Gate |
|------|--------------|
| `internal/api/ai_handlers.go` | Chat endpoints, patrol endpoints |
| `internal/ai/patrol.go` | Patrol service start |
| `internal/ai/service.go` | AI chat service |
| `internal/ai/alert_triggered.go` | Alert analysis |
| `internal/api/oidc_handlers.go` | OIDC/SSO configuration |
| `internal/api/kubernetes_handlers.go` | K8s cluster endpoints |
| `internal/monitoring/kubernetes/` | K8s monitoring service |
**Example gating in ai_handlers.go:**
```go
func (h *AISettingsHandler) HandleChat(w http.ResponseWriter, r *http.Request) {
// Check Pro license
if !h.licenseService.HasFeature(license.FeatureAIChat) {
utils.WriteJSONError(w, http.StatusPaymentRequired,
"AI Chat requires Pulse Pro. Visit https://pulserelay.pro to upgrade.")
return
}
// ... existing logic
}
```
---
## Phase 3: Frontend Implementation
### 3.1 New Settings Tab: "Pro License"
Location: `frontend-modern/src/routes/settings/+page.svelte` (or equivalent)
```
┌──────────────────────────────────────────────────────────────┐
│ ⚡ Pulse Pro │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ License Key │ │
│ │ [________________________________________________] │ │
│ │ [Activate License] │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ✅ License Status: Active (Pro) │
│ 📧 Licensed to: user@example.com │
│ 📅 Expires: Never (Lifetime) │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ Included Features: │
│ ✅ AI Chat Assistant │
│ ✅ AI Patrol (Background Health Checks) │
│ ✅ AI Alert Analysis │
│ ✅ Priority Support │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ Don't have a license? │
│ [Get Pulse Pro →] https://pulserelay.pro │
│ │
└──────────────────────────────────────────────────────────────┘
```
### 3.2 Graceful Degradation for Unlicensed Users
When AI features are accessed without a license:
- **AI Settings Tab**: Show features but disabled with "Upgrade to Pro" message
- **Chat Button**: Show but with "Pro" badge, clicking prompts upgrade
- **Patrol Findings**: Hide or show "Enable with Pro" placeholder
**Don't be hostile.** The free version should still feel complete. Pro is an enhancement, not a hostage situation.
---
## Phase 4: Payment & License Generation
### 4.1 Payment Processor: LemonSqueezy
**Why LemonSqueezy over alternatives?**
- Handles global VAT/sales tax automatically
- Generates invoices (enterprises need this)
- Good webhook support for automation
- Reasonable fees (~5% + 50¢)
- Supports both subscription and one-time payments
### 4.2 Pricing Structure (Suggested)
| Tier | Price | Features | Target |
|------|-------|----------|--------|
| **Pro Monthly** | $12/month | AI features, OIDC/SSO, K8s monitoring | Individuals |
| **Pro Annual** | $99/year | Same as monthly, 2 months free | Power users |
| **Pro Lifetime** | $249 one-time | All Pro features, forever | Homelabbers who hate subscriptions |
| **MSP** | $49/month | All Pro + unlimited instances, white-label, multi-tenant | MSPs |
| **Enterprise** | Custom | All features + support SLA, on-prem license server | Large orgs |
### 4.3 Feature Matrix
| Feature | Free | Pro | MSP | Enterprise |
|---------|------|-----|-----|------------|
| Proxmox VE/PBS/PMG monitoring | ✅ | ✅ | ✅ | ✅ |
| Docker/Podman monitoring | ✅ | ✅ | ✅ | ✅ |
| Alerts (Discord, Slack, etc.) | ✅ | ✅ | ✅ | ✅ |
| Metrics history | ✅ | ✅ | ✅ | ✅ |
| Backup explorer | ✅ | ✅ | ✅ | ✅ |
| **AI Chat** | ❌ | ✅ | ✅ | ✅ |
| **AI Patrol** | ❌ | ✅ | ✅ | ✅ |
| **AI Alert Analysis** | ❌ | ✅ | ✅ | ✅ |
| **OIDC/SSO** | ❌ | ✅ | ✅ | ✅ |
| **Kubernetes monitoring** | ❌ | ✅ | ✅ | ✅ |
| Unlimited instances | ❌ | ❌ | ✅ | ✅ |
| White-label branding | ❌ | ❌ | ✅ | ✅ |
| Multi-tenant mode | ❌ | ❌ | ✅ | ✅ |
| Priority support | ❌ | Email | Email | Dedicated |
| SLA | ❌ | ❌ | ❌ | ✅ |
### 4.3 License Generation Service
A simple Cloudflare Worker or Vercel Edge Function:
```javascript
// Simplified license generator (LemonSqueezy webhook handler)
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const webhook = await request.json()
if (webhook.meta.event_name === 'order_created') {
const license = generateLicense({
email: webhook.data.attributes.user_email,
tier: 'pro',
expiresAt: null, // lifetime for now
})
// Send license via email
await sendLicenseEmail(webhook.data.attributes.user_email, license)
}
return new Response('OK')
}
function generateLicense(data) {
// Sign JWT with private key
// Return base64-encoded license key
}
```
---
## Phase 5: Launch Communication
### 5.1 Changelog Entry
```markdown
## v5.0.0 - The AI Update
### 🚀 Major Changes
**Introducing Pulse Pro**
Pulse 5.0 includes powerful AI features that require a Pro license:
- **AI Chat**: Natural language interface to your infrastructure
- **AI Patrol**: Background health monitoring and insights
- **AI Alert Analysis**: Smart analysis when alerts fire
Core monitoring features remain **completely free and open source**.
Pro licenses support ongoing development and enable me to work on Pulse full-time.
[Get Pulse Pro →](https://pulserelay.pro)
---
*Pulse has grown from a weekend project to something used by thousands.
To keep improving it, I need to make it sustainable. Thank you for your support!*
— Richard
```
### 5.2 Preemptive FAQ
Add to README or docs:
**Q: Why are AI features paid?**
A: AI features require significant development effort and ongoing maintenance. Pro licenses let me work on Pulse sustainably while keeping core monitoring free.
**Q: Will monitoring features become paid?**
A: No. Proxmox/Docker/K8s monitoring, alerts, history, and all current free features will remain free forever.
**Q: What if I'm already using AI in the RC?**
A: Thank you for testing! RC users were beta testers helping shape these features. The final release requires a Pro license.
**Q: I can't afford Pro.**
A: Email me (richard@pulserelay.pro). I offer discounts for students, hobbyists in financial hardship, and open source contributors.
**Q: Can I self-host without Pro?**
A: Absolutely. Pulse works great without AI features. Pro is optional.
---
## Implementation Order
1. **Week 1: Backend**
- [ ] Create `internal/license/` package
- [ ] Implement JWT validation with embedded public key
- [ ] Add license persistence (encrypted storage)
- [ ] Gate AI endpoints with license checks
- [ ] Add `/api/license` endpoints (check, activate)
2. **Week 2: Frontend + Payment**
- [ ] Add Pro License settings tab
- [ ] Update AI settings to show Pro-gated state
- [ ] Set up LemonSqueezy product
- [ ] Create license generation webhook
- [ ] Set up pulserelay.pro landing page (can be simple)
- [ ] Write announcement blog post
3. **Launch**
- [ ] Release v5.0.0 stable
- [ ] Post to Reddit (/r/homelab, /r/Proxmox, /r/selfhosted)
- [ ] Post to GitHub Discussions
- [ ] Email mailing list (if you have one)
---
## Security Considerations
1. **Private key**: Never commit to repo. Store in password manager + secure backup.
2. **License validation**: Always verify signature, never trust claims without verification.
3. **Obfuscation**: Consider light obfuscation of license check code (not for security, but to discourage trivial patching).
4. **Grace period**: If validation fails, maybe grant 7-day grace period before disabling (better UX).
---
## What NOT to Do
- ❌ Phone-home license validation (breaks air-gapped installs)
- ❌ Aggressive license enforcement (pisses off users)
- ❌ Remove free features to "encourage" upgrades
- ❌ Make the free version feel crippled
- ❌ Hide that it's paid (be upfront in README)
---
## Success Metrics (First 90 Days)
| Metric | Target |
|--------|--------|
| Pro licenses sold | 50-100 |
| Monthly revenue | $500-$1000 |
| Churn rate | <5% |
| Negative community reactions | <10 vocal complaints |
| GitHub stars lost | <50 |
If you hit these numbers, you've validated the model. Then you can expand to MSP tier, add features, etc.
---
*This plan can be adjusted based on your preferences. Want me to help implement any specific part?*