Skip to main content
A Rego policy defines the rules Kosli evaluates trail data against. You pass a .rego file to kosli evaluate trail or kosli evaluate trails via the --policy flag. Kosli includes a built-in evaluator with no OPA installation required.

Policy contract

These rules are Kosli-specific conventions, not OPA built-ins. Kosli queries data.policy.* to find them.
package policy
required
Every policy must declare package policy. Kosli queries data.policy.allow and data.policy.violations to read the result.
allow
boolean
required
Must evaluate to a boolean. Kosli exits with code 0 when true, code 1 when false.Always define allow with a fail-safe default and drive it through a positive assertion, not through the absence of violations. See Safe policy design.
violations
set of strings
Optional but recommended. A set of human-readable strings explaining why the policy denied. Kosli displays these when allow is false. Each message should identify the offending resource and the reason.Violations are diagnostics only. They must not drive the allow decision. See Safe policy design.

Safe policy design

Three rules prevent a policy from incorrectly reporting a non-compliant trail as compliant.

Rule 1: use a fail-safe default

Always start with default allow := false. A trail must be explicitly approved rather than allowed by the absence of evidence against it. Use parameter aliases at the top of the policy file rather than hardcoding threshold values. If a required param is absent from the params file, any rule that references its alias will fail to evaluate, and allow will correctly remain false.
See Evaluate trails with OPA policies for a detailed walkthrough.

Rule 2: drive allow through positive assertions

Drive the allow decision through a condition that must be true for the trail to be compliant. Do not write:
When a violations rule body encounters an undefined reference, such as a missing param or an absent attestation field, OPA silently skips that rule body and adds no message to the set. The set is then empty, count(violations) == 0 evaluates to true, and allow fires even though the policy never verified compliance. This produces a false-positive compliant result. The safe pattern makes compliance explicit:
If any field referenced inside trail_is_compliant is undefined, the rule body fails to evaluate and allow remains false. See Evaluate trails with OPA policies for a detailed walkthrough.

Rule 3: violations are diagnostics only

In a violations rule, an undefined reference causes the rule body to fail silently: no message is added. This is the safe failure mode for diagnostics. Violations explain a denial determined by the allow rule and must not determine it themselves. See Evaluate trails with OPA policies for a detailed walkthrough.

Params

Policies can read external configuration via the --params flag. Params are available in the policy as data.params.*. This separates policy logic from the thresholds it enforces, so one .rego file can cover multiple environments with different params files.
Alias params at the top of the policy file so that missing values cause rules to fail rather than silently proceeding:
If max_high is absent, max_high is undefined and any rule that references it fails to evaluate, leaving allow at its false default.

Input data

The data structure passed to the policy as input depends on which command you use.

Single trail (kosli evaluate trail)

The policy receives input.trail, a single trail object.
input.trail
object
The trail being evaluated.

Multiple trails (kosli evaluate trails)

The policy receives input.trails, an array of trail objects with the same structure as input.trail above.
input.trails
array
Array of trail objects. Each element has the same structure as input.trail described above.
Use --show-input with --output json to print the full input structure for a given trail. Pipe through jq to explore specific fields:

Local testing

Use kosli evaluate input to test a policy against captured trail data without making live Kosli API calls:

Exit codes

CodeMeaning
0Policy allowed (allow = true)
1Policy denied (allow = false) or command error (network failure, invalid Rego, policy file not found)
Exit code 1 is used for both denial and failure. To distinguish between them in CI, use --output json and read the allow field directly from the output rather than relying on the exit code.

Examples

Check pull request approvals across multiple trails

Allows only when every trail in input.trails has at least one pull request with at least one approver. The attestation name is read from params so the same policy works across orgs that use different naming conventions.

Check Snyk scan results on a single trail

Allows only when every artifact in the trail has a Snyk scan where the high-severity vulnerability count does not exceed max_high. Both the attestation name and the threshold are read from params.

Further reading

Last modified on May 21, 2026