package checker import ( "context" "fmt" sdk "git.happydns.org/checker-sdk-go/checker" ) // Default values for shared and per-rule options. Kept here so documentation // (Definition / rule Options()) and runtime reads stay in sync. const ( defaultMaxChainLength = 8 defaultMinTargetTTL = 60 defaultRequireResolvableTarget = true defaultAllowApexCNAME = false defaultRecognizeApexFlattening = true // hintKey is the CheckState.Meta key that carries a short remediation // suggestion. The HTML report surfaces it as the "How to fix" block. hintKey = "hint" ) // loadAlias reads the primary AliasData observation. When the observation is // missing or malformed, it returns a single StatusError state ready to be // returned by the rule. func loadAlias(ctx context.Context, obs sdk.ObservationGetter) (*AliasData, []sdk.CheckState) { var data AliasData if err := obs.Get(ctx, ObservationKeyAlias, &data); err != nil { return nil, []sdk.CheckState{{ Status: sdk.StatusError, Message: fmt.Sprintf("failed to read alias observation: %v", err), }} } return &data, nil } // skipped wraps a single StatusInfo state describing why a rule did not fire. // Rules must always return at least one state; "skipped" is how we encode // "this rule has nothing to judge right now" without masking the check. func skipped(reason string) []sdk.CheckState { return []sdk.CheckState{{ Status: sdk.StatusInfo, Message: "skipped: " + reason, }} } // okState builds a single StatusOK result for rules whose condition is clean. func okState(subject, message string) []sdk.CheckState { return []sdk.CheckState{{ Status: sdk.StatusOK, Subject: subject, Message: message, }} } // withHint attaches a remediation hint to a state's Meta. No-op when hint is // empty so callers can hand through the option unconditionally. func withHint(s sdk.CheckState, hint string) sdk.CheckState { if hint == "" { return s } if s.Meta == nil { s.Meta = map[string]any{} } s.Meta[hintKey] = hint return s } // apexKnown is the gate most chain-oriented rules apply: when apex lookup // failed there is nothing to evaluate. Rules that gate on this return // skipped("apex lookup failed") uniformly so the UI shows a consistent line. func apexKnown(data *AliasData) bool { return data.ApexLookupError == "" && data.Apex != "" } // allowApexCNAME reads the shared option governing whether a CNAME at apex is // downgraded to a warning. func allowApexCNAME(opts sdk.CheckerOptions) bool { return sdk.GetBoolOption(opts, "allowApexCNAME", defaultAllowApexCNAME) } // recognizeApexFlattening reads the shared option governing whether // provider-side ALIAS/ANAME flattening is recognised (and A/AAAA alongside a // CNAME at apex is excused from coexistence). func recognizeApexFlattening(opts sdk.CheckerOptions) bool { return sdk.GetBoolOption(opts, "recognizeApexFlattening", defaultRecognizeApexFlattening) }