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 ¶
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.
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 ¶
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.
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.
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.
Types ¶
type Client ¶
Client calls the Polar license endpoints.
func NewClient ¶
func NewClient() *Client
NewClient builds a client from build-time defaults and environment overrides.
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.
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.