Skip to content
kix /docs
Install the CLI

How-to guide Policy, CI, and compliance

Add scorecard rules

Enable built-in policy checks and add a custom rule to a cluster.

Scorecard rules run while Kix evaluates a cluster. Every built-in rule set runs by default. Narrow the set when you want fewer checks, and add custom rules for policy specific to your packages or organization.

This guide assumes the cluster is defined with kix.buildCluster.

scorecard.rules defaults to kix.rules, the four built-in categories: security, reliability, governance, and architecture. Setting the option replaces that default, so name every set you want to keep:

cluster.nix
scorecard.rules = {
inherit (kix.rules) security reliability;
};

The attribute name becomes the rule category. For example, kix.rules.reliability.hasProbes is reported as reliability.hasProbes.

To keep the whole built-in set and change one rule, leave rules alone and use an override instead. See Disable scorecard rules and Override scorecard severity.

Place custom rules under a category of your own. This tested package-level rule applies only to packages that advertise the reverse-proxy capability, then checks their evaluated configuration:

tutorials/19-scorecards/scorecard.nix
custom.proxyMaxBodySizeMustBeExplicit = {
description = "Reverse-proxy gateways must set maxBodySize explicitly (not the 1m default).";
level = "package";
severity = "error";
tags = [ "reliability" "kix-examples" ];
# Only run on reverse-proxy packages. `appliesTo` receives the
# package metadata directly, so this checks `meta.provides`.
appliesTo =
{ meta, ... }:
builtins.elem "reverse-proxy" (meta.provides or [ ]);
check =
{ config, instanceName, ... }:
if (config.maxBodySize or "") == "1m" then
[
{
message =
"instance '${instanceName}' uses the default maxBodySize '1m'. "
+ "nginx rejects larger request bodies — set this explicitly.";
}
]
else
[ ];
};

View source on GitHub ↗

Add the rule inside scorecard.rules. Its full name is custom.proxyMaxBodySizeMustBeExplicit. Because setting rules replaces the default, merge the custom category into the built-in set to keep both:

cluster.nix
scorecard.rules = kix.rules // {
custom.proxyMaxBodySizeMustBeExplicit = { /* the rule above */ };
};

Every rule declares a level that determines the value passed to its check:

  • manifest runs once for each rendered Kubernetes resource.
  • package runs once for each package instance.
  • namespace runs once for each namespace.
  • cluster runs once for the whole cluster.

Kix accepts only these four levels and three severities: info, warning, and error. Evaluation rejects any other value. This prevents misspelled levels from creating rules that never run, and misspelled severities from being treated as warnings.

The check returns one finding for each problem and an empty list when the input passes. Use appliesTo when a rule is meaningful only for a subset of its level.

Run the cluster checks after adding or changing a rule:

kix-examples/
❱ kix check 19-scorecards
 TOOL       RESULT  DETAILS                      
 eval       pass    24 manifests evaluated       
 scorecard  pass    0 errors, 6 warnings, 2 info

Kix reports the number of scorecard errors, warnings, and informational findings. Every finding is capped at scorecard.maxSeverity, which defaults to warning, so a new cluster prints what the rules found and still builds. With the cap raised to error, an error-severity finding becomes a failed assertion. Kix collects the failed assertions, reports them together, and does not build the cluster. Because evaluation failed, kix check reports the failure in its eval step rather than producing a separate scorecard summary. Warnings and informational findings are collected across the cluster and reported together when evaluation succeeds. See Fail the build on scorecard findings for the cap.