Documentation
¶
Overview ¶
Package lifecycle provides the dormant-plugin state machine for the nSelf plugin license lifecycle. It handles active → dormant → expired transitions, persistent JSON state storage, and the 7-day default grace period.
TOCTOU protection: Save uses an atomic temp-file rename so concurrent CLI invocations cannot corrupt the store. The caller must ensure it holds the store in memory for only the duration of a single operation — no long-held in-memory caches — to avoid read/check/write races across processes.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Record ¶
type Record struct {
Name string `json:"name"`
State State `json:"state"`
LicenseExpiry time.Time `json:"license_expiry"`
DormantSince *time.Time `json:"dormant_since,omitempty"`
// GracePeriod is persisted per-record so that global config changes cannot
// retroactively shorten a grace period already in progress.
GracePeriod time.Duration `json:"grace_period"`
}
Record tracks a single plugin's license lifecycle state.
type State ¶
type State string
State represents the current license lifecycle state of a plugin.
const ( // StateActive means the plugin license is valid and the plugin runs normally. StateActive State = "active" // StateDormant means the license expired but the grace period is still active. // The plugin continues to function during this window with a daily warning banner. StateDormant State = "dormant" // StateExpired means the grace period is exhausted. The plugin is disabled and // queued for auto-removal on the next `nself build`. StateExpired State = "expired" // DefaultGracePeriod is the time a plugin stays dormant before auto-removal. DefaultGracePeriod = 7 * 24 * time.Hour )
type Store ¶
Store is the persistent state for all plugin lifecycle records. It is serialised to ~/.config/nself/plugin-lifecycle.json.
func Load ¶
Load reads the persistent store from disk. If the file does not exist a new empty store is returned so the caller can populate it without special-casing first-run behaviour.
func (*Store) CheckExpiry ¶
CheckExpiry transitions plugins from active → dormant → expired based on now. It returns two slices:
- dormant: plugins newly transitioned to StateDormant this call.
- autoRemove: plugins transitioned to StateExpired (auto-removal candidates).
The caller must call Save after CheckExpiry to persist any transitions. Call MarkRenewal before CheckExpiry for any plugin whose license was renewed this session so it cannot immediately cycle back to expired.
func (*Store) MarkRenewal ¶
MarkRenewal transitions a plugin back to StateActive with a new expiry. If no record exists for name it is created. DormantSince is cleared so the grace period counter resets on the next CheckExpiry call.