Documentation
¶
Overview ¶
Package license implements offline, self-hosted license validation for agnt Pro features. Licenses are hyperboloide/lk blobs: an ECDSA (P-384) signature over a JSON Payload. The signing private key never ships; the binary embeds only the public key (see key.go) and validates fully offline.
Index ¶
- Constants
- Variables
- func GenerateKeypair() (privB32, pubB32 string, err error)
- func Load() (string, error)
- func Mint(privKeyB32 string, p *Payload) (string, error)
- func Remove() error
- func Save(blob string) error
- func SetVerifyKeyForTest(k *lk.PublicKey) (restore func())
- type Capability
- type GateError
- type Manager
- type Payload
- type State
- type Status
Constants ¶
const GracePeriod = 14 * 24 * time.Hour
GracePeriod is how long Pro features keep working past Expiry before they hard-block. Warnings surface throughout the window.
Variables ¶
var ErrInvalidLicense = errors.New("license: signature verification failed")
ErrInvalidLicense is returned by Validate when a blob fails verification.
var ErrNoLicense = errors.New("license: no license installed")
ErrNoLicense is returned by Load when no license blob is stored.
Functions ¶
func GenerateKeypair ¶ added in v0.13.20
GenerateKeypair returns a fresh (private, public) base32 keypair for operator / server setup (`agnt license keygen`). The public half is embedded in the client; the private half is the signing key.
func Load ¶ added in v0.13.20
Load reads the stored license blob. ErrNoLicense if none is installed.
func Mint ¶ added in v0.13.20
Mint signs a payload into a license blob using the base32-encoded private signing key, returning the base32 blob handed to a customer.
This is the integration seam for the Stripe webhook → license issuance flow: a future self-hosted service builds a Payload from the customer record and calls Mint with the signing key kept server-side. Kept client-side too for manual issuance (`agnt license issue`) and tests. The private key must NEVER be embedded in or distributed with the client binary.
func Remove ¶ added in v0.13.20
func Remove() error
Remove deletes the stored license blob. Absent file is not an error.
func Save ¶ added in v0.13.20
Save writes the license blob atomically (temp file + rename) at mode 600.
func SetVerifyKeyForTest ¶ added in v0.13.20
SetVerifyKeyForTest overrides the verification key and returns a restore func. Test-only: production code never calls it.
Types ¶
type Capability ¶ added in v0.13.20
type Capability string
Capability is a Pro capability key. A license payload lists the capabilities it grants; Check authorizes a feature only if its capability is granted and the license is in a serving state.
const ( // CapWholeSite gates whole-site / multi-page crawling and operations // (vs. the free single-page tools). CapWholeSite Capability = "whole_site" // CapAnalysisReport gates generated analysis / reporting features. CapAnalysisReport Capability = "analysis_report" // CapComponentExtract gates component-library / CSS extraction from a // codebase. CapComponentExtract Capability = "component_extract" // CapAdvancedTesting gates the advanced testing suite. CapAdvancedTesting Capability = "advanced_testing" )
type GateError ¶ added in v0.13.20
type GateError struct {
Capability Capability
State State
}
GateError is returned by Check when a Pro capability is denied. It carries the deciding state so callers can tailor messaging.
type Manager ¶ added in v0.13.20
type Manager struct {
// contains filtered or unexported fields
}
Manager loads and caches the installed license, and is the single chokepoint Pro features consult via Check. Validation (ECDSA verify) happens once at load, never on the hot path.
func NewManager ¶ added in v0.13.20
func NewManager() *Manager
NewManager returns an unloaded Manager. Call Load (or let Check lazy-load) before relying on its state.
func NewManagerForTest ¶ added in v0.13.20
NewManagerForTest returns a Manager preloaded with the given Status, bypassing disk load and signature validation. It exists so external-package tests can build a Manager that grants (or denies) a capability deterministically. For tests only — production code must use NewManager + Load.
func (*Manager) Check ¶ added in v0.13.20
func (m *Manager) Check(cap Capability) (warning string, err error)
Check authorizes a Pro capability. It returns nil when the license is in a serving state (Valid or Grace) and grants cap; otherwise a *GateError. When the state is Grace, it also returns a non-empty warning the caller should surface (the error is still nil — Pro is allowed during grace).
func (*Manager) Load ¶ added in v0.13.20
Load reads, verifies, and evaluates the stored license, caching the result. A missing license is not an error — it yields StateMissing. A present but unverifiable blob yields StateInvalid (also not an error: the agent should see the state, not a failure). Returns an error only for unexpected I/O.
type Payload ¶ added in v0.13.20
type Payload struct {
// Email identifies the licensee. Informational only — not an auth boundary.
Email string `json:"email"`
// CustomerID is the upstream (Stripe) customer reference, for support and
// re-issue. Informational only.
CustomerID string `json:"customer_id,omitempty"`
// Plan is a human label for the tier (e.g. "team", "enterprise").
Plan string `json:"plan,omitempty"`
// IssuedAt records when the license was minted (UTC).
IssuedAt time.Time `json:"issued_at"`
// Expiry is when the paid term ends (UTC). After this, the license enters
// the grace window (see Evaluate) before Pro features hard-block.
Expiry time.Time `json:"expiry"`
// Capabilities lists the Pro capability keys this license grants. A Check
// for a capability not present here fails even on a fully valid license.
Capabilities []string `json:"capabilities,omitempty"`
}
Payload is the JSON document carried inside a signed license blob. It is the single source of truth for who a license is for, when it expires, and which Pro capabilities it grants. The signing server (Stripe webhook → issue.Mint) builds this from the customer record; the client only ever reads it.
func Validate ¶ added in v0.13.20
Validate verifies a license blob against the embedded public key and decodes its payload. A tampered, wrong-key, or malformed blob yields ErrInvalidLicense (wrapped). The blob is the base32 string handed to the customer.
func (*Payload) Grants ¶ added in v0.13.20
func (p *Payload) Grants(cap Capability) bool
Grants reports whether the payload authorizes the given capability.
type State ¶ added in v0.13.20
type State int
State is the serving state of a stored license.
const ( // StateMissing means no license blob is stored. StateMissing State = iota // StateInvalid means a blob is stored but failed signature/parse. StateInvalid // StateValid means the license is signed and within its paid term. StateValid // StateGrace means past Expiry but within GracePeriod — Pro still serves, // with a warning. StateGrace // StateExpired means past Expiry + GracePeriod — Pro blocks. StateExpired )