checker: expose standalone /check route via CheckerInteractive

Implements RenderForm/ParseForm on the provider: users can hit /check
with just a domain name; ParseForm resolves CAA records via direct DNS
queries (walking up the label tree per RFC 8659) and hands the SDK a
synthetic service payload so the standard Collect → Evaluate pipeline
runs without a happyDomain host. TLS probes are not gathered here, so
the rule reports StatusUnknown for the TLS cross-check in this mode.
This commit is contained in:
nemunaire 2026-04-23 11:29:39 +07:00
commit 1d562e7aa4

View file

@ -36,6 +36,7 @@ func (p *caaProvider) ParseForm(r *http.Request) (sdk.CheckerOptions, error) {
return nil, errors.New("domain is required")
}
domain = dns.Fqdn(domain)
bare := strings.TrimSuffix(domain, ".")
records, err := lookupCAA(domain)
if err != nil {
@ -55,12 +56,12 @@ func (p *caaProvider) ParseForm(r *http.Request) (sdk.CheckerOptions, error) {
svc := serviceMessage{
Type: serviceType,
Domain: strings.TrimSuffix(domain, "."),
Domain: bare,
Service: svcBody,
}
return sdk.CheckerOptions{
"domain": strings.TrimSuffix(domain, "."),
"domain": bare,
"service": svc,
}, nil
}
@ -74,12 +75,12 @@ func lookupCAA(fqdn string) ([]CAARecord, error) {
return nil, err
}
c := new(dns.Client)
for name := fqdn; name != "" && name != "."; {
msg := new(dns.Msg)
msg.SetQuestion(name, dns.TypeCAA)
msg.RecursionDesired = true
c := new(dns.Client)
in, _, err := c.Exchange(msg, resolver)
if err != nil {
return nil, err