Extend the admin backup to cover checker configurations, plans,
evaluations and executions — previously these were stored but silently
lost on restore. Add RestoreX storage methods so primary records keep
their original Id and secondary indexes are rebuilt (Create* generates
new IDs, Update* requires an existing record to clean stale indexes).
Wire UserQuota.MaxChecksPerDay field into the scheduler via the
UserGater: an in-memory daily counter per user
(reset at UTC midnight): gates scheduled executions, with a two-tier
heuristic that skips short-interval jobs first once the budget is 80%
consumed so rare/important checks are not starved by frequent
pings. Planned executions returned by ListPlannedExecutions are marked
with a new ExecutionRateLimited status when the user is over
budget. Manual API triggers bypass the quota.
Add a job-level gate to the scheduler. When set, the gate is consulted
on every popped job; if it returns false, the job is skipped and
re-enqueued for its next interval without invoking the engine.
A new UserGater builds such a gate from a user resolver and an
inactivity threshold:
- users with UserQuota.SchedulingPaused are always blocked (admin
kill switch);
- users whose LastSeen is older than their effective inactivity
horizon (UserQuota.InactivityPauseDays, falling back to a system
default) are blocked until they log in again;
- lookups are cached for 5 minutes so the scheduler hot path stays
cheap, with an Invalidate hook for use on user updates.
This addresses the "free trial then forgotten" failure mode described
in the design notes.
Implement the checker business logic:
- CheckerOptionsUsecase: scope-based option resolution, validation,
auto-fill from execution context (domain, zone, service)
- CheckPlanUsecase: CRUD for user scheduling configurations
- CheckStatusUsecase: aggregated status queries, execution history
- CheckerEngine: full execution pipeline (observe, evaluate, aggregate)
- Scheduler: background job executor with auto-discovery, min-heap
queue, worker pool, and jitter-based scheduling