licensing

package
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package license validates Anvil Pro license keys against Polar.sh's customer-portal API (no merchant secret needed — the endpoints are public and scoped by organization ID). State is cached on disk so a licensed server keeps running through network trouble: validation is retried daily and a cached success is honored for a 14-day grace window.

Anvil's source is MIT; the gate is honest-but-real. If you strip it, you know what you did.

Index

Constants

View Source
const DefaultAPI = "https://api.polar.sh/v1/customer-portal"

DefaultAPI is Polar's customer-portal base URL. Overridable with ANVIL_LICENSE_API for tests and self-hosted mocks.

View Source
const Grace = 14 * 24 * time.Hour

Grace is how long a cached successful validation keeps Pro features on when revalidation cannot reach the API.

Variables

View Source
var BuyURL = "https://goforge.dev/anvil/#pro"

BuyURL is where an unlicensed deployment is pointed. Overridable at build time once the live checkout link exists.

View Source
var ErrUnreachable = errors.New("license: validation service unreachable")

ErrUnreachable wraps transport-level failures: the verdict is unknown, so callers fall back to the grace window rather than treating the key as bad.

View Source
var OrgID = ""

Set at build time:

go build -ldflags "-X goforge.dev/anvil/licensing.OrgID=<polar org id>"

Overridable at runtime with ANVIL_LICENSE_ORG (forks, tests).

Functions

func DefaultPath

func DefaultPath() string

DefaultPath is where license state lives: $XDG_CONFIG_HOME/anvil or ~/.config/anvil.

func IsInvalid

func IsInvalid(err error) bool

IsInvalid reports whether err is a definitive rejection (as opposed to the service being unreachable).

Types

type Client

type Client struct {
	API   string // base URL; default DefaultAPI
	OrgID string
	HTTP  *http.Client
}

Client calls the Polar license endpoints.

func NewClient

func NewClient() *Client

NewClient builds a client from build-time defaults and environment overrides.

func (*Client) Activate

func (c *Client) Activate(key, label string) (string, error)

Activate registers this deployment as one activation of the key and returns the activation ID, which subsequent validations must present.

func (*Client) Validate

func (c *Client) Validate(key, activationID string) (*Info, error)

Validate checks the key (and activation, when present) and returns its current standing.

type Info

type Info struct {
	Valid     bool
	Status    string // granted | revoked | disabled | expired | not_found
	ExpiresAt time.Time
}

Info is the verdict on a key.

type Manager

type Manager struct {
	Client *Client
	Path   string
	Now    func() time.Time // tests; defaults to time.Now
}

Manager ties the client to the state file.

func NewManager

func NewManager() *Manager

NewManager builds a manager with environment-aware defaults.

func (*Manager) Activate

func (m *Manager) Activate(key, label string) (*State, error)

Activate activates and validates a key, then persists the state.

func (*Manager) Check

func (m *Manager) Check() (bool, *State, error)

Check revalidates the stored key and reports whether Pro features are on. Decision table:

  • no state file → false
  • API says valid → true (state refreshed)
  • API definitively rejects → false (status recorded)
  • API unreachable → true iff LastValid within Grace

func (*Manager) Load

func (m *Manager) Load() (*State, error)

Load reads the state file; a missing file returns (nil, nil).

type State

type State struct {
	Key          string    `json:"key"`
	ActivationID string    `json:"activation_id,omitempty"`
	Label        string    `json:"label,omitempty"`
	LastValid    time.Time `json:"last_valid"`       // last successful validation
	Status       string    `json:"status,omitempty"` // last known status
	ExpiresAt    time.Time `json:"expires_at,omitempty"`
}

State is the on-disk record of this deployment's license.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL