Move server.go and interactive.go (and their tests) from the root
checker/ package into checker/server/. Plugin and builtin consumers of
the SDK now import only checker/ and no longer drag net/http,
html/template, or the form-rendering code into their artifacts: on
checker-dane.so this drops the binary by ~1.2 MB and removes 170
html/template symbols along with the net/http contribution that came
from the SDK itself.
Breaking for standalone consumers (main.go):
NewServer(p) -> server.New(p)
CheckerInteractive -> server.Interactive
InteractiveRelatedProviders -> server.Siblings
Providers that only satisfy the interactive interfaces structurally
(method set match, no explicit type reference) need no source change;
only main.go has to switch its import path and the constructor name.
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.
Add the plumbing that lets a checker receive (at evaluation, report
rendering, and metrics extraction) observations produced by other
checkers on DiscoveryEntry records it originally published.
Surface changes:
- RelatedObservation struct: one downstream observation, tagged with
the producing CheckerID and the Ref matching the DiscoveryEntry
it covers.
- ObservationGetter gains GetRelated(ctx, key), so rules can opt in
to cross-checker composition. mapObservationGetter (remote
/evaluate path) returns empty; the host owns lineage resolution.
- ReportContext interface: Data() + Related(key). Reporters consume
it instead of a raw json.RawMessage, which collapses the former
legacy/Ctx duplicate and gives one uniform signature:
GetHTMLReport(ctx ReportContext) (string, error)
ExtractMetrics(ctx ReportContext, t time.Time) ([]CheckMetric, error)
- NewReportContext(data, related) and StaticReportContext(data) build
fixed-payload contexts for entry points without an ObservationContext.
- ExternalReportRequest gains a Related map so the host can ship
pre-composed lineage to a remote checker over /report. The SDK's
/report handler threads it through to the reporter via
NewReportContext, closing the wire gap that previously forced
remote reports to a StaticReportContext with no related data.
Tests cover the Related map round-trip end-to-end via a peeking provider.
Adds HealthResponse carrying inflight count, total requests, 1/5/15-min
EWMA load averages, uptime, and NumCPU so a scheduler can pick the least
busy worker. A background sampler updates the load averages every 5s,
stopped by a new idempotent Close method. Work endpoints (/collect,
/evaluate, /report) are wrapped with a trackWork middleware; /health
and /definition are excluded so polling traffic does not pollute the
signal.
Errors from provider.Collect() and json.Marshal were returned with HTTP
200, making failures invisible to monitoring, proxies, and clients that
check status codes. Return 500 Internal Server Error so HTTP-level
tooling can detect failures without parsing the response body.