feat(license): two deployments times three tiers, and two new limits
Plans are keyed on (deployment, tier) rather than tier alone, which is what ends Free being cloud-only by construction - there is a self-hosted Free plan now, so the one-per-account rule has to be enforced per deployment instead of falling out of the plan table. tier self_hosted becomes a legacy value no new licence carries. NormaliseTier maps it to self-hosted Professional, which is what it always granted, so blobs we cannot re-sign keep working. Limits.FillUnset exists because a licence signed before a field existed decodes it as 0, and 0 would read as no monitors and an audit log trimmed to nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -68,7 +68,8 @@ func issue(args []string) {
|
||||
instanceID := fs.String("instance-id", "", "instance UUID the licence is bound to (required)")
|
||||
instanceName := fs.String("instance-name", "", "display name")
|
||||
accountID := fs.String("account-id", "", "admin-side account id, optional")
|
||||
tier := fs.String("tier", "", "free | professional | self_hosted (required)")
|
||||
tier := fs.String("tier", "", "free | professional | enterprise (required)")
|
||||
deployment := fs.String("deployment", "cloud", "cloud | self_hosted")
|
||||
term := fs.String("term", "1y", "1m or 1y")
|
||||
expires := fs.String("expires", "", "explicit RFC3339 expiry, overrides --term")
|
||||
out := fs.String("out", "", "write the blob to this file instead of stdout")
|
||||
@@ -78,9 +79,9 @@ func issue(args []string) {
|
||||
fatal("--instance-id and --tier are required")
|
||||
}
|
||||
|
||||
plan, ok := license.PlanFor(*tier)
|
||||
plan, ok := license.PlanFor(*deployment, *tier)
|
||||
if !ok {
|
||||
fatal("unknown tier %q", *tier)
|
||||
fatal("no plan for deployment %q tier %q", *deployment, *tier)
|
||||
}
|
||||
|
||||
key := os.Getenv("LICENSE_SIGNING_KEY")
|
||||
@@ -107,7 +108,7 @@ func issue(args []string) {
|
||||
|
||||
// Self Hosted is sold annually only, so the window in which a cancelled
|
||||
// licence keeps working is bounded at a year.
|
||||
if plan.Tier == license.TierSelfHosted && *term == "1m" && *expires == "" {
|
||||
if plan.Deployment == license.DeploymentSelfHosted && *term == "1m" && *expires == "" {
|
||||
fatal("self_hosted is annual only; use --term=1y or an explicit --expires")
|
||||
}
|
||||
|
||||
@@ -123,6 +124,7 @@ func issue(args []string) {
|
||||
InstanceName: name,
|
||||
Tier: plan.Tier,
|
||||
Deployment: plan.Deployment,
|
||||
SupportLevel: plan.SupportLevel,
|
||||
IssuedAt: now,
|
||||
ExpiresAt: exp,
|
||||
Limits: plan.Limits,
|
||||
|
||||
Reference in New Issue
Block a user