checker: adopt unified ReportContext reporter signature

Follow the checker-sdk-go interface consolidation: reporter methods
now take sdk.ReportContext and read the payload via ctx.Data() instead
of the raw json.RawMessage parameter. Backed by the same underlying
logic — this is a signature migration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
nemunaire 2026-04-19 23:36:04 +07:00
commit df4a7a89d1
9 changed files with 480 additions and 32 deletions

View file

@ -4,15 +4,25 @@ import (
"fmt"
"html/template"
"strings"
sdk "git.happydns.org/checker-sdk-go/checker"
)
// RenderReport turns an Observation into a self-contained HTML document.
//
// The report foregrounds action items for the failure modes we see most often
// (well-known misconfig, missing DAV capability, missing credentials) before
// showing the full per-phase evidence.
func RenderReport(obs *Observation, title string) (string, error) {
data := buildReportData(obs, title)
// (well-known misconfig, missing DAV capability, missing credentials,
// downstream TLS issues on the endpoints we published) before showing the
// full per-phase evidence.
//
// tlsRelated is the output of ctx.Related(TLSRelatedKey) at report time. Nil
// is fine: the TLS section is simply omitted. This is how the happyDomain
// cross-checker composition story (see
// happydomain3/docs/checker-discovery-endpoint.md) surfaces certificate
// alerts on the CalDAV/CardDAV service page rather than in a parallel TLS
// dashboard.
func RenderReport(obs *Observation, title string, tlsRelated []sdk.RelatedObservation) (string, error) {
data := buildReportData(obs, title, tlsRelated)
var buf strings.Builder
if err := reportTemplate.Execute(&buf, data); err != nil {
return "", fmt.Errorf("render dav report: %w", err)
@ -21,15 +31,16 @@ func RenderReport(obs *Observation, title string) (string, error) {
}
type reportData struct {
Title string
Domain string
Verdict string
VerdictCls string
Callouts []calloutData
Phases []phaseData
Raw string
ShowSched bool
Scheduling *SchedulingResult
Title string
Domain string
Verdict string
VerdictCls string
Callouts []calloutData
Phases []phaseData
Raw string
ShowSched bool
Scheduling *SchedulingResult
TLSSummaries []TLSSummary
}
type calloutData struct {
@ -51,7 +62,7 @@ type phaseItem struct {
Mono string
}
func buildReportData(o *Observation, title string) reportData {
func buildReportData(o *Observation, title string, tlsRelated []sdk.RelatedObservation) reportData {
d := reportData{
Title: title,
Domain: o.Domain,
@ -61,6 +72,21 @@ func buildReportData(o *Observation, title string) reportData {
d.Callouts = buildCallouts(o)
d.Phases = buildPhases(o)
// Fold downstream TLS probes (published by checker-tls against the
// endpoints we discovered) into the report.
tlsSummaries, tlsCallouts := foldTLSRelated(tlsRelated)
d.TLSSummaries = tlsSummaries
for _, c := range tlsCallouts {
d.Callouts = append(d.Callouts, calloutData{
Severity: c.Severity,
Title: c.Title,
Body: c.Body,
})
}
if len(tlsSummaries) > 0 {
d.Phases = append(d.Phases, buildTLSPhase(tlsSummaries))
}
switch {
case hasSeverity(d.Phases, "fail"):
d.Verdict = "Critical issues detected"
@ -225,6 +251,26 @@ func buildPhases(o *Observation) []phaseData {
return phases
}
// buildTLSPhase turns per-endpoint TLS summaries into a collapsible phase
// rendered at the bottom of the report. Open when anything is non-OK so
// operators don't need to expand it to see the problem.
func buildTLSPhase(summaries []TLSSummary) phaseData {
p := phaseData{Title: "TLS (from checker-tls)"}
for _, s := range summaries {
label := s.Address
if s.TLSVersion != "" {
label = fmt.Sprintf("%s — %s", s.Address, s.TLSVersion)
}
p.Items = append(p.Items, phaseItem{
Label: label,
Status: s.Status,
Detail: s.Detail,
})
}
p.Open = hasItemSeverity(p.Items, "warn", "fail")
return p
}
// ── small helpers used by buildPhases ────────────────────────────────────────
func wellKnownStatus(d DiscoveryResult) string {