check

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package check implements `cadish check`: it loads a Cadishfile (resolving `import` directives), then produces a per-site complexity report — the headline differentiator of cadish. The report estimates how expensive a config is to evaluate per request (regex evaluations, weighted cost, directive depth by lifecycle phase), flags dead/unreachable rules and unknown names, and offers optimization suggestions.

The cadishfile AST is semantics-free; every classification here (which phase a directive runs in, whether a matcher is a regex, whether a rule is dead) is applied by this package using its own directive catalog.

Index

Constants

This section is empty.

Variables

PhaseOrder is the canonical display order for phases.

Functions

func WriteJSONError

func WriteJSONError(w io.Writer, path string, strict bool, err error) error

WriteJSONError renders a top-level check failure (a root-file parse or read error, returned by Check before any Report exists) as a structured JSON object to w, so a `-json` consumer always receives valid, machine-readable JSON even when the config does not parse — instead of empty stdout. The shape mirrors a failed report: ok=false, one error diagnostic, no sites. path and strict are echoed so the JSON is self-describing and its outcome agrees with the (non-zero) exit code.

Types

type CostBreakdown

type CostBreakdown struct {
	Exact int `json:"exact"`
	Glob  int `json:"glob"`
	Regex int `json:"regex"`
}

CostBreakdown explains the estimated per-request cost: counts of evaluated predicates by weight class. Cost = Exact*1 + Glob*2 + Regex*10.

func (CostBreakdown) Cost

func (c CostBreakdown) Cost() int

Cost returns the weighted total.

type Diagnostic

type Diagnostic struct {
	Severity Severity `json:"severity"`
	// Position is "file:line:col" (empty file renders as "<input>").
	Position string `json:"position"`
	// Code is a short stable machine code, e.g. "unknown-directive".
	Code string `json:"code"`
	// Message is the human-readable explanation.
	Message string `json:"message"`
	// contains filtered or unexported fields
}

Diagnostic is a single finding tied to a source position.

type Phase

type Phase string

Phase is a request-lifecycle phase. Directives are grouped by the phase in which they execute.

const (
	// PhaseSetup is parse-once configuration (tls, cache, upstream, …); it does
	// not run per request.
	PhaseSetup Phase = "SETUP"
	// PhaseRECV is the request phase (respond, purge, route, pass).
	PhaseRECV Phase = "RECV"
	// PhaseKEY builds the cache key (cache_key).
	PhaseKEY Phase = "KEY"
	// PhaseORIGIN runs on a miss, against the origin response (cache_ttl, storage).
	PhaseORIGIN Phase = "ORIGIN"
	// PhaseDELIVER is the response phase (header, strip_cookies, cors).
	PhaseDELIVER Phase = "DELIVER"
)

type Report

type Report struct {
	Path string `json:"path"`
	// Diagnostics holds file-level findings not tied to a single site
	// (e.g. import resolution failures).
	Diagnostics []Diagnostic  `json:"diagnostics,omitempty"`
	Sites       []*SiteReport `json:"sites"`
}

Report is the full result of a check run.

func Check

func Check(path string) (*Report, error)

Check loads the Cadishfile at path, resolves its imports, and analyzes it into a complexity Report. A parse or read error on the *root* file is returned as err (a *cadishfile.ParseError or os error) so the caller can print a "file:line:col" diagnostic; all other findings — including import failures and per-site warnings — live in the returned Report.

func CheckSource

func CheckSource(filename string, src []byte) (*Report, error)

CheckSource analyzes already-parsed source. filename is used for positions and for resolving imports relative to its directory. It is the in-memory analogue of Check, used in tests.

func CheckSourceSandboxed

func CheckSourceSandboxed(filename string, src []byte) (*Report, error)

CheckSourceSandboxed is the sandboxed variant of CheckSource for use in the admin playground (/api/validate). It performs NO filesystem access: import directives are blocked (a clear diagnostic is emitted instead of reading the file) and geo/maxmind path probes are skipped. All non-filesystem diagnostics (unknown directives, arity errors, matcher issues, etc.) are still produced.

This prevents the admin endpoint from becoming an arbitrary host-file read primitive when an attacker submits a config containing `import /etc/passwd` or `geo { source maxmind /run/secrets/... }`.

func (*Report) Counts

func (r *Report) Counts() (errors, warnings int)

Counts returns the total number of error- and warning-severity diagnostics across the whole report.

func (*Report) ExitCode

func (r *Report) ExitCode(strict bool) int

ExitCode is the process exit code: non-zero when there are errors, or — under strict — any warnings.

func (*Report) WriteJSON

func (r *Report) WriteJSON(w io.Writer, strict bool) error

WriteJSON renders the report as indented JSON to w (for tooling). strict reflects whether the check ran under -strict, so the emitted JSON's outcome fields ("ok"/"strict") agree with the process exit code: under -strict a warnings-only report is a failure ("ok":false) even though "errors":0.

func (*Report) WriteText

func (r *Report) WriteText(w io.Writer) error

WriteText renders the report as a human-readable text report to w.

type Severity

type Severity string

Severity classifies a diagnostic. Errors fail the check (non-zero exit); warnings only fail under -strict.

const (
	// SevError is a hard problem: a parse/import failure or a config mistake
	// that makes the report unsound.
	SevError Severity = "error"
	// SevWarning is advisory: unknown names, dead rules, light arity issues.
	SevWarning Severity = "warning"
)

type SiteReport

type SiteReport struct {
	Addresses []string `json:"addresses"`
	Position  string   `json:"position"`

	// MatcherCount is the number of named matcher definitions in scope.
	MatcherCount int `json:"matcher_count"`
	// DirectiveCount is the total number of directives in scope.
	DirectiveCount int `json:"directive_count"`
	// RegexEvalsPerRequest is how many regex matchers (path_regex/host_regex/
	// regex-valued header) a request evaluates on the hot path.
	RegexEvalsPerRequest int `json:"regex_evals_per_request"`
	// PhaseCounts is directive count grouped by lifecycle phase.
	PhaseCounts map[Phase]int `json:"phase_counts"`
	// EstimatedCost is the weighted per-request cost (see CostBreakdown).
	EstimatedCost int           `json:"estimated_cost"`
	CostBreakdown CostBreakdown `json:"cost_breakdown"`

	Suggestions []string     `json:"suggestions,omitempty"`
	Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
}

SiteReport is the complexity report for one site (or the synthetic "(top-level)" scope for a bare imported fragment).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL