| title | Working with controls |
|---|---|
| description | Learn how to define controls in Kosli, record decisions against them, and track compliance across your software delivery process. |
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
- Install Kosli CLI (v2.12.0 or higher).
- Get a Kosli API token.
- Have at least one Flow and Trail already created.
export KOSLI_ORG=<your-org>
export KOSLI_API_TOKEN=<your-api-token>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.Create a control by providing a control code, a name, and optionally a description and a source URL pointing back to the authoritative definition.
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| Flag | Description |
|---|---|
--code |
Required. 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. |
--name |
Required. A human-readable label for the control (e.g. Source code review). Mutable — you can rename a control while keeping the same code. |
--description |
Optional. What the control does, in human-readable terms. |
--source-url |
Optional. URL back to the authoritative definition in your GRC system, ServiceNow, or policy document. |
kosli list controlsYou can also navigate to Controls in the Kosli app sidebar to browse your controls catalog.
For larger catalogs, use the API or CLI in a script to mirror your existing controls from ServiceNow or a spreadsheet:
# Example: create several controls in a loop from a CSV
while IFS=, read -r code name description source_url; do
kosli create control \
--code "$code" \
--name "$name" \
--description "$description" \
--source-url "$source_url"
done < controls.csvThe API also supports this natively, making it straightforward to write a sync script or ask an LLM to generate one from your existing catalog.
You can update the name, description, and source URL of a control. The control code is immutable.
kosli update control RCTL-043 \
--name "Source code review (never alone)" \
--description "Updated description."Each modification creates a new version of the control. This means decisions recorded against a control reference the specific version of the definition that was current when the decision was made.
Controls can be archived but never deleted. Archived controls retain their audit history and their code cannot be reused.
kosli archive control RCTL-043A 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 \
--outcome pass \
--name "source-code-review-decision" \
--description "All 14 commits in this release have been reviewed by a second developer."| Flag | Description |
|---|---|
--control |
Required. The control code this decision is recorded against. |
--outcome |
Required. The outcome of the decision: pass or fail. |
--name |
The attestation slot name on the trail. |
--description |
Optional human-readable context for the decision. |
--attachments |
Optional evidence file(s) to attach (e.g. an evaluation report, a REGO policy output). |
The decision attestation goes on a trail, like any other attestation. It affects trail compliance: a fail 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).
- name: Record source code review decision
run: |
kosli attest decision \
--flow ${{ env.KOSLI_FLOW }} \
--trail ${{ env.KOSLI_TRAIL }} \
--control RCTL-043 \
--outcome pass \
--name source-code-review-decision \
--description "Reviewed by ${{ github.actor }} — all commits have approved PRs."For controls where you want to capture the evidence or policy used, attach a file:
kosli attest decision \
--flow my-release-flow \
--trail my-release-trail \
--control RCTL-1866 \
--outcome pass \
--name supply-chain-integrity-decision \
--attachments evaluation-report.jsonEnvironment policies can require a positive decision outcome for a named control, rather than relying on attestation name or type. This abstracts the policy from the specific tooling your pipelines use: instead of "has an attestation of type snyk with zero criticals", you express "control vuln-scan-production has been satisfied."
Add a controls key to your environment policy YAML alongside existing attestation requirements:
allow_list:
- artifact_provider: docker
require_provenance: true
require_trail_attestations:
- name: pull-request
controls:
- RCTL-043
- RCTL-1866With this policy in place, an artifact cannot be deployed to this environment unless a pass decision has been recorded for each listed control on the artifact's trail.
kosli get artifact my-app@sha256:abc123 --controlsThis shows which controls have decisions recorded for this artifact, whether those decisions are pass or fail, and which controls have no decision recorded at all (the coverage gap).
kosli list decisions --control RCTL-043You can also filter by flow, environment, or time range:
kosli list decisions \
--control RCTL-043 \
--environment production \
--from 2026-01-01Navigate to Controls in the Kosli app and select a control to see its compliance view. This shows:
- Deployments by control — a list of deployments where this control was referenced, with pass/fail status, filterable by repository, flow, and environment.
- Coverage — the ratio of deployments where the control was evidenced 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 control satisfaction rates across staging and production.
You have learned how to define controls in Kosli, record decisions against them from pipelines, enforce them in environment policies, and query 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 been evidenced, and which haven't?"
From here you can:
- Learn more about environment policies
- Learn more about attestations
- Evaluate trails with Rego policies to automate decision-making
- Explore the Controls API reference for programmatic catalog management