checker: let CheckRule.Evaluate return per-subject CheckStates

Rules that iterate over multiple elements (certificates, CAA records,
nameservers, …) previously had to squash per-element results into a
single concatenated message. Evaluate now returns []CheckState and
CheckState carries an opaque Subject, so each element gets its own
structured state. The server injects a StatusUnknown placeholder when
a rule returns nothing, to avoid silently dropping the rule.
This commit is contained in:
nemunaire 2026-04-23 10:06:48 +07:00
commit d847c71a50
3 changed files with 30 additions and 9 deletions

View file

@ -182,11 +182,15 @@ func (s Status) String() string {
}
}
// CheckState is the result of evaluating a single rule.
// CheckState is the result of evaluating a single rule on a single subject.
// Subject is opaque to the SDK: producers and consumers agree on its shape
// (a hostname, a record key, a serial, …). Leave Subject empty for rules
// that produce a single, global result.
type CheckState struct {
Status Status `json:"status"`
Message string `json:"message"`
Code string `json:"code,omitempty"`
Subject string `json:"subject,omitempty"`
Meta map[string]any `json:"meta,omitempty"`
}
@ -222,11 +226,20 @@ type CheckRuleInfo struct {
Options *CheckerOptionsDocumentation `json:"options,omitempty"`
}
// CheckRule evaluates observations and produces a CheckState.
// CheckRule evaluates observations and produces one or more CheckStates.
//
// Evaluate returns a slice so a rule iterating over multiple elements can
// emit one state per subject (each carrying CheckState.Subject) without
// squashing them into a single concatenated message.
//
// Evaluate must not return a nil or empty slice: callers expect at least
// one state per rule. When a rule finds nothing to evaluate, return a
// single CheckState with an appropriate status (typically StatusInfo or
// StatusOK) describing that fact.
type CheckRule interface {
Name() string
Description() string
Evaluate(ctx context.Context, obs ObservationGetter, opts CheckerOptions) CheckState
Evaluate(ctx context.Context, obs ObservationGetter, opts CheckerOptions) []CheckState
}
// CheckRuleWithOptions is an optional interface that rules can implement