mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-10 00:14:38 +00:00
The in-app updater and install.sh both fetch the public community build from github.com/rcourtman/Pulse. On non-Docker Pro installs (systemd, proxmoxve, source) the "Apply Update" button was live, so applying an update replaced the separately compiled Pro binary with community and silently stripped Audit, RBAC, Reporting, and SSO from a paying customer. Docker was already blocked; nothing else was. Add a dependency-free pkg/edition marker (defaults to community) that the Pro binary flips via enterpriseruntime.Initialize, mirroring the existing coreaudit.SetLogger / server.SetBusinessHooks registration seam. ApplyUpdate now refuses when the edition is Pro, pointing at the Private Release Access portal (https://pulserelay.pro/download.html) and the install.sh --archive path. The gate keys off the compiled binary, not license state: a community binary with an active license still self-updates as before. The update banner hides the in-app apply affordance and shows portal instructions for the Pro runtime, keyed off the existing runtime-identity signal (runtime.build) rather than a new payload field, so nothing extra is plumbed through the version API and the frontend reuses the canonical "which binary am I" contract. The backend gate is the hard guarantee; the banner is the UX layer. Guard 2 of the Pro download/update experience spec.
63 lines
2 KiB
Go
63 lines
2 KiB
Go
// Package edition records which compiled Pulse binary is running: the public
|
|
// community build or the separately compiled Pulse Pro build (Audit, RBAC,
|
|
// Reporting, and SSO compiled in).
|
|
//
|
|
// It is a small public registration seam that mirrors the existing
|
|
// coreaudit.SetLogger / server.SetBusinessHooks pattern: the community binary
|
|
// leaves the default (Community) in place, and only the Pro binary flips it to
|
|
// Pro during enterpriseruntime.Initialize. The marker keys off the compiled
|
|
// binary, never off license-active state — a community binary with an active
|
|
// license is still community and must keep its normal self-update behaviour.
|
|
//
|
|
// This lives in pkg/ rather than internal/ because pulse-enterprise is a
|
|
// separate Go module and cannot import internal/ packages. Keeping it
|
|
// dependency-free also lets internal/updates consult it without any import
|
|
// cycle against pkg/server (which transitively imports internal/updates).
|
|
package edition
|
|
|
|
import (
|
|
"strings"
|
|
"sync/atomic"
|
|
)
|
|
|
|
const (
|
|
// Community is the public, open-source Pulse build.
|
|
Community = "community"
|
|
// Pro is the separately compiled Pulse Pro build.
|
|
Pro = "pro"
|
|
)
|
|
|
|
// current holds the running binary's edition. It always stores a string, so
|
|
// atomic.Value is safe here and lets read paths (HTTP handlers) run lock-free.
|
|
var current atomic.Value
|
|
|
|
func init() {
|
|
current.Store(Community)
|
|
}
|
|
|
|
// SetEdition records the running binary's edition. Any value other than Pro
|
|
// normalizes to Community so a mis-wired caller can never silently claim Pro.
|
|
// Call once during startup registration.
|
|
func SetEdition(name string) {
|
|
current.Store(normalize(name))
|
|
}
|
|
|
|
// Current returns the running binary's edition (Community or Pro).
|
|
func Current() string {
|
|
if v, ok := current.Load().(string); ok && v != "" {
|
|
return v
|
|
}
|
|
return Community
|
|
}
|
|
|
|
// IsPro reports whether the running binary is the compiled Pulse Pro edition.
|
|
func IsPro() bool {
|
|
return Current() == Pro
|
|
}
|
|
|
|
func normalize(name string) string {
|
|
if strings.EqualFold(strings.TrimSpace(name), Pro) {
|
|
return Pro
|
|
}
|
|
return Community
|
|
}
|