Skip to main content
Controls in Kosli represent the named, identifiable governance requirements that your organisation enforces across software delivery — things like “source code review”, “no hard-coded credentials”, or “vulnerability scan passed”. They are the things auditors ask about, the things compliance teams track, and the things governance platform engineers build automation around. Without controls as first-class entities, Kosli can tell you that an attestation was made, but not which governance requirement it satisfies. Controls close that gap: they connect the evidence you collect in pipelines to the specific requirements that auditors, control owners, and regulators care about. This tutorial covers how to:
  • Define a control library in Kosli that mirrors your existing controls catalog
  • Record decision outcomes against controls from your pipelines
  • Reference controls in environment policies
  • View control compliance across deployments

Prerequisites

Setup

export KOSLI_ORG=<your-org>
export KOSLI_API_TOKEN=<your-api-token>

Understanding controls

Before creating controls, it helps to understand how they fit into the Kosli data model. Raw fact attestations are the evidence you collect in pipelines — test results, vulnerability scans, pull request approvals. These are facts about what happened. Decisions are recorded judgements about a specific control: “control RCTL-043 is satisfied for this artifact.” A decision is an attestation that references a control, recorded at the point where a judgement is made — typically during a release or promotion step. Controls are the named governance requirements that decisions are recorded against. They have a stable identity (the control code), a human-readable name, and an optional description and source link pointing back to your GRC system or policy document. This separation matters: raw facts exist independently of controls. A JUnit test report is a fact. Whether that test report satisfies a “test coverage” control is a decision. The decision references the fact; the fact doesn’t need to know about the control.
Kosli holds a mirror to your existing control definitions — it does not replace your GRC system or ServiceNow instance. The control catalog in Kosli is a lightweight copy that enables querying and coverage visibility.

Creating a control

Navigate to Controls in the Kosli app sidebar and select New control. Provide a control code, a name, and optionally a description and a source URL pointing back to the authoritative definition in your GRC system or policy document. You can also create controls via the CLI:
kosli create control \
    --code RCTL-043 \
    --name "Source code review" \
    --description "All commits included in a release must have been reviewed by at least one person other than the author." \
    --source-url https://your-grc-system.example.com/controls/RCTL-043
FlagDescription
--codeRequired. The customer-provided control identifier (e.g. RCTL-043, peer-review, vuln-scan-production). Must be unique within your organisation. Immutable once created — to change a control code, archive the control and create a new one.
--nameRequired. A human-readable label for the control (e.g. Source code review). Mutable — you can rename a control while keeping the same code.
--descriptionOptional. What the control does, in human-readable terms.
--source-urlOptional. URL back to the authoritative definition in your GRC system, ServiceNow, or policy document.
Control codes are the stable identity that pipelines, environment policies, and reports reference. Choose codes that match how your organisation already refers to controls — for example, the identifiers in your ServiceNow or GRC system. If you use RCTL-043 today, use exactly that.

List your controls

Navigate to Controls in the Kosli app sidebar to browse your full controls catalog. Each control shows its code, name, current version, and a decision coverage indicator that reflects the health of that control across your pipelines. Control definitions are versioned: each time you update a control’s name, description, or source URL, a new version is created. This matters for audits — decisions recorded against a control always reference the exact version of the definition that was current when the decision was made, so the audit trail is precise even as controls evolve over time.
StatusMeaning
ActiveA passing decision has been recorded against this control recently.
StaleDecisions were recorded in the past but none recently — pipelines may have stopped recording decisions against this control.
No decisionsThis control exists in the catalog but no decision has ever been recorded against it. A dark control.
Controls catalog showing Active, Stale, and No decisions coverage indicators alongside version badges, a View archived filter, and an expanded version history for RCTL-043
You can also list controls via the CLI:
kosli list controls

Recording a decision against a control

A decision is how you record that a control has been satisfied (or not) for a specific artifact or trail. Record a decision using the kosli attest decision command, which creates an attestation of the built-in decision type and links it to a named control.
kosli attest decision \
    --flow my-release-flow \
    --trail my-release-trail \
    --control RCTL-043 \
    --compliant true \
    --name "source-code-review-decision" \
    --description "All 14 commits in this release have been reviewed by a second developer."
FlagDescription
--controlRequired. The control code this decision is recorded against.
--compliantRequired. Whether the control is satisfied: true or false.
--nameThe attestation slot name on the trail.
--descriptionOptional human-readable context for the decision.
--attachmentsOptional evidence file(s) to attach (e.g. an evaluation report, a REGO policy output).
--user-dataOptional path to a JSON file containing additional structured data to attach to the attestation.
The decision attestation goes on a trail, like any other attestation. It affects trail compliance: a --compliant false decision makes the trail non-compliant. There are no restrictions on which flow or trail a decision can be recorded on — place it wherever makes sense in your process, typically at the point where the decision is actually being made (e.g. during a release preparation or promotion step).
A decision is a recorded judgement. How you arrive at the decision — running kosli evaluate, executing a custom script, or using a third-party tool — is up to you. The attest decision command records the outcome; it does not make the decision for you.

Attaching evidence to a decision

Evidence attached to a decision explains why the decision was reached — not just that a control passed or failed, but what information was used to make that judgement. This is what auditors will ask for: the policy that was applied and the evaluation report that justified the outcome. A natural source of evidence is a kosli evaluate report. The example below evaluates a trail against a Rego policy, captures the full JSON report, and attaches both the policy file and the report to the decision attestation. See Evaluate trails with OPA policies for a full walkthrough of kosli evaluate.
# Run the evaluation and save the full JSON report
kosli evaluate trail "$TRAIL_NAME" \
    --policy supply-chain-policy.rego \
    --org "$KOSLI_ORG" \
    --flow "$FLOW_NAME" \
    --output json > eval-report.json 2>/dev/null || true

# Read the allow/deny result from the report
is_compliant=$(jq -r '.allow' eval-report.json)

# Extract violations as structured user-data
jq '{violations: .violations}' eval-report.json > eval-violations.json

# Record the decision, attaching the policy and evaluation report as evidence
kosli attest decision \
    --flow "$FLOW_NAME" \
    --trail "$TRAIL_NAME" \
    --control RCTL-1866 \
    --compliant="$is_compliant" \
    --name supply-chain-integrity-decision \
    --attachments supply-chain-policy.rego,eval-report.json \
    --user-data eval-violations.json
This creates a decision attestation with:
  • --attachments containing the Rego policy (for reproducibility) and the full JSON evaluation report
  • --user-data containing the violations, which appear in the Kosli UI as structured metadata on the attestation
  • --compliant set directly from the evaluation result

Referencing controls in environment policies

Environment policies define the requirements an artifact must satisfy before it can run in a given environment. You can require that specific named controls have a passing decision recorded — not just that the trail is generally compliant. This is the key distinction: rather than relying on trail compliance as a catch-all, you can make individual controls explicit policy gates.
prod-policy.yaml
_schema: https://kosli.com/schemas/policy/environment/v1
artifacts:
  provenance:
    required: true
  controls:
    - RCTL-043
    - RCTL-1866
With this policy in place, an artifact deployed to this environment will be marked non-compliant if a passing decision has not been recorded for each listed control on its trail. The artifact can still be deployed — Kosli records compliance state but does not block deployments by default. To gate deployments on compliance, use kosli assert in your pipeline. This abstracts the policy from the specific tooling your pipelines use: instead of “has an attestation of type snyk with zero criticals”, the policy expresses “control RCTL-1866 has been satisfied” — and the decision attestation carries the evidence of how that judgement was reached. For the complete policy syntax, including attestation requirements and exceptions, see the Environment Policies page.

Viewing control compliance

Navigate to Controls in the Kosli app and select a control to see its detail view. Each control has three tabs: Decisions, Deployments, and Coverage.

Decisions

The Decisions tab is the default view. It lists every decision attestation recorded against this control across all flows and trails, with the artifact, flow, trail, environment, who recorded the decision, when, and whether the outcome was compliant or non-compliant. Each decision also shows which version of the control definition was in effect when it was recorded. Use the flow, environment, and outcome filters to narrow the list.
Decisions tab for RCTL-043 showing a list of decision attestations with artifact, flow, trail, environment, recorded-by, date, and compliant/non-compliant outcome

Deployments

The Deployments tab shows where artifacts with decisions against this control have been deployed, with compliant/non-compliant status per deployment, filterable by repository, flow, and environment.
Deployments tab for RCTL-043 showing deployments with compliant and non-compliant decisions

Coverage

The Coverage tab shows the ratio of deployments where a decision was recorded vs. those where it was not. This is the key metric: controls without decisions are the blind spots that auditors will ask about. Use the environment filter to compare decision recording rates across staging and production.
Coverage tab for RCTL-043 showing decision recorded vs. no decision recorded deployments and 78% coverage rate

What you’ve accomplished

You have learned how to define controls in Kosli, record decisions against them from pipelines, enforce them in environment policies, and view compliance across deployments. Your controls catalog is now the bridge between the evidence Kosli collects and the requirements your auditors, control owners, and regulators care about. For each production change, you can now answer: “which of our controls have decisions recorded, and which don’t?” From here you can:
Last modified on April 16, 2026