|
| 1 | +--- |
| 2 | +title: "Controls" |
| 3 | +description: "A proposed model for representing governance controls as first-class entities in Kosli, with decisions recorded against them." |
| 4 | +tag: "Concept" |
| 5 | +--- |
| 6 | + |
| 7 | +import { ConceptBanner } from '/snippets/kosli-next-banner.mdx'; |
| 8 | + |
| 9 | +<ConceptBanner /> |
| 10 | + |
| 11 | +## The problem |
| 12 | + |
| 13 | +Today, Kosli can tell you _that_ an attestation was made on a trail, but not _which governance requirement it satisfies_. Auditors, compliance teams, and governance engineers think in terms of named controls - "source code review", "no hard-coded credentials", "vulnerability scan passed" - and they want to answer questions like: |
| 14 | + |
| 15 | +- Which of our controls have evidence recorded against them, and which don't? |
| 16 | +- For this release, which controls passed and which failed? |
| 17 | +- How much of our production estate is covered by control `RCTL-1866`? |
| 18 | + |
| 19 | +Right now, those questions are hard to answer in Kosli without bespoke reporting on top of raw attestations. |
| 20 | + |
| 21 | +## The proposed approach |
| 22 | + |
| 23 | +We are considering adding **controls** as first-class entities in Kosli. A control would be a stable, named governance requirement - mirrored from your existing controls catalog in ServiceNow, a GRC system, or a policy document. Pipelines would record **decisions** against controls, and environment policies would reference controls by identifier. |
| 24 | + |
| 25 | +Three new building blocks would sit alongside the existing data model: |
| 26 | + |
| 27 | +- **Raw fact attestations** (unchanged) are the evidence you collect in pipelines: test results, vulnerability scans, pull request approvals. |
| 28 | +- **Decisions** are recorded outcomes of a Policy Decision Point (PDP) - the moment a judgement is reached about a specific control for a specific artifact. A decision would be an attestation that references a control. |
| 29 | +- **Controls** are the named governance requirements that decisions are recorded against. They would have a stable identifier, a human-readable name, and an optional description and source URL pointing back to the authoritative definition. |
| 30 | + |
| 31 | +Raw facts would continue to exist independently of controls. A JUnit report is a fact. Whether it satisfies a "test coverage" control would be a decision. The decision references the fact; the fact would not need to know about the control. |
| 32 | + |
| 33 | +Kosli would hold a mirror to your existing control definitions - it would not replace your GRC system. The catalog in Kosli would be a lightweight copy that enables querying and coverage visibility. |
| 34 | + |
| 35 | +## How it would work |
| 36 | + |
| 37 | +The walkthrough below is **illustrative**. CLI flags, YAML schema, and UI shown here are sketches to make the proposal concrete - they are not implemented and the shapes will change based on feedback. |
| 38 | + |
| 39 | +### Defining a control |
| 40 | + |
| 41 | +A control would be created from the Kosli app or the CLI, mirroring an entry in your existing catalog: |
| 42 | + |
| 43 | +```bash |
| 44 | +kosli create control \ |
| 45 | + --identifier RCTL-043 \ |
| 46 | + --name "Source code review" \ |
| 47 | + --description "All commits included in a release must have been reviewed by at least one person other than the author." \ |
| 48 | + --source-url https://your-grc-system.example.com/controls/RCTL-043 |
| 49 | +``` |
| 50 | + |
| 51 | +The **identifier** would be the stable identity (immutable once created); name, description, and source URL would be mutable and versioned, so the audit trail stays precise as controls evolve. |
| 52 | + |
| 53 | +The catalog view would surface a **coverage indicator** per control: |
| 54 | + |
| 55 | +| Status | Meaning | |
| 56 | +|--------|---------| |
| 57 | +| **Active** | A passing decision has been recorded within the last 28 days. | |
| 58 | +| **Stale** | Decisions in the past, but none in the last 28 days - pipelines may have stopped recording against this control. | |
| 59 | +| **No decisions** | Defined in the catalog, but no decision ever recorded. A dark control. | |
| 60 | + |
| 61 | +<Frame> |
| 62 | + <img src="/images/kosli_next/controls/controls-list.png" alt="Controls catalog showing Active, Stale, and No decisions coverage indicators alongside version badges and an expanded version history for RCTL-043" /> |
| 63 | +</Frame> |
| 64 | + |
| 65 | +### Recording a decision |
| 66 | + |
| 67 | +A decision would record the outcome of a PDP against a named control, scoped to a specific artifact: |
| 68 | + |
| 69 | +```bash |
| 70 | +kosli attest decision \ |
| 71 | + --flow my-release-flow \ |
| 72 | + --trail my-release-trail \ |
| 73 | + --fingerprint "$ARTIFACT_FINGERPRINT" \ |
| 74 | + --control RCTL-043 \ |
| 75 | + --compliant true \ |
| 76 | + --name "source-code-review-decision" \ |
| 77 | + --description "All 14 commits in this release have been reviewed by a second developer." |
| 78 | +``` |
| 79 | + |
| 80 | +The decision attestation would land on a trail like any other attestation and affect trail compliance. The PDP itself - whether you run `kosli evaluate` with a Rego policy, a bespoke script, or a third-party tool - would remain entirely yours. `kosli attest decision` would record the outcome; it would not make the decision for you. |
| 81 | + |
| 82 | +A natural pairing is `kosli evaluate`, which already runs Rego policies against trail evidence. Its JSON output could be captured and recorded as the decision, with the policy and report attached as evidence: |
| 83 | + |
| 84 | +```bash |
| 85 | +kosli evaluate trail "$TRAIL_NAME" \ |
| 86 | + --policy supply-chain-policy.rego \ |
| 87 | + --org "$KOSLI_ORG" \ |
| 88 | + --flow "$FLOW_NAME" \ |
| 89 | + --output json > eval-report.json |
| 90 | + |
| 91 | +is_compliant=$(jq -r '.allow' eval-report.json) |
| 92 | + |
| 93 | +kosli attest decision \ |
| 94 | + --flow "$FLOW_NAME" \ |
| 95 | + --trail "$TRAIL_NAME" \ |
| 96 | + --fingerprint "$ARTIFACT_FINGERPRINT" \ |
| 97 | + --control RCTL-1866 \ |
| 98 | + --compliant="$is_compliant" \ |
| 99 | + --name supply-chain-integrity-decision \ |
| 100 | + --attachments supply-chain-policy.rego,eval-report.json |
| 101 | +``` |
| 102 | + |
| 103 | +### Referencing controls in environment policies |
| 104 | + |
| 105 | +Environment policies would gain a `controls` key. Instead of expressing requirements in tooling-specific terms ("has a Snyk attestation with zero criticals"), the policy would express the governance outcome ("control `RCTL-1866` has been satisfied"). The decision attestation would carry the evidence of how that judgement was reached. |
| 106 | + |
| 107 | +```yaml prod-policy.yaml |
| 108 | +_schema: https://docs.kosli.com/schemas/policy/v1 |
| 109 | +artifacts: |
| 110 | + provenance: |
| 111 | + required: true |
| 112 | + controls: |
| 113 | + - RCTL-043 |
| 114 | + - RCTL-1866 |
| 115 | +``` |
| 116 | +
|
| 117 | +An artifact deployed to this environment would be marked non-compliant if a passing decision is missing for any listed control. The Policy Enforcement Point (PEP) would be `kosli assert artifact --environment`, used in a pipeline step to gate promotion on control compliance. |
| 118 | + |
| 119 | +### The end-to-end flow |
| 120 | + |
| 121 | +The sequence below shows how a single artifact would move through a build trail and a release trail, with the decision made at release time and enforced when the release controller checks the environment policy. |
| 122 | + |
| 123 | +```mermaid |
| 124 | +sequenceDiagram |
| 125 | + participant P as Pipeline |
| 126 | + participant K as Kosli |
| 127 | +
|
| 128 | + rect rgb(220,235,255) |
| 129 | + Note over P,K: Build trail |
| 130 | + P->>K: kosli begin trail build-123 --flow my-app |
| 131 | + P->>K: kosli attest pullrequest github ... |
| 132 | + P->>K: kosli attest artifact artifact-a ... |
| 133 | + end |
| 134 | +
|
| 135 | + rect rgb(255,235,215) |
| 136 | + Note over P,K: Release trail |
| 137 | + P->>K: kosli begin trail release-456 --flow my-release |
| 138 | + Note right of P: PDP - evaluate RCTL-043 |
| 139 | + P->>K: kosli evaluate trail release-456 --policy rctl-043.rego --output json |
| 140 | + K-->>P: eval-report.json |
| 141 | + P->>K: kosli attest decision --control RCTL-043 --compliant $IS_COMPLIANT ... |
| 142 | + end |
| 143 | +
|
| 144 | + rect rgb(220,255,220) |
| 145 | + Note over P,K: Release controller |
| 146 | + Note right of P: PEP - assert against environment policy |
| 147 | + P->>K: kosli assert artifact --fingerprint $FP_A --environment production |
| 148 | + K-->>P: exit 0 |
| 149 | + end |
| 150 | +``` |
| 151 | + |
| 152 | +### Viewing compliance |
| 153 | + |
| 154 | +A per-control detail view would show three perspectives: |
| 155 | + |
| 156 | +**Decisions** - every decision attestation recorded against this control, with artifact, flow, trail, environment, recorded-by, date, outcome, and which version of the control definition was in effect. |
| 157 | + |
| 158 | +<Frame> |
| 159 | + <img src="/images/kosli_next/controls/controls-decisions.png" alt="Decisions tab for RCTL-043 listing decision attestations with artifact, flow, trail, environment, recorder, date, and compliant/non-compliant outcome" /> |
| 160 | +</Frame> |
| 161 | + |
| 162 | +**Deployments** - where artifacts with decisions against this control have been deployed, with compliant/non-compliant status per deployment. |
| 163 | + |
| 164 | +<Frame> |
| 165 | + <img src="/images/kosli_next/controls/controls-compliance-deployments.png" alt="Deployments tab for RCTL-043 showing deployments with compliant and non-compliant decisions" /> |
| 166 | +</Frame> |
| 167 | + |
| 168 | +**Coverage** - the ratio of deployments where a decision was recorded vs. those where it was not. Controls without decisions would be the blind spots auditors will ask about. |
| 169 | + |
| 170 | +<Frame> |
| 171 | + <img src="/images/kosli_next/controls/controls-compliance-coverage.png" alt="Coverage tab for RCTL-043 showing decision recorded vs. no decision recorded deployments and a 78% coverage rate" /> |
| 172 | +</Frame> |
| 173 | + |
| 174 | +## Open questions |
| 175 | + |
| 176 | +We would love feedback on: |
| 177 | + |
| 178 | +- **Identifier conventions.** Should Kosli enforce a format for control identifiers, or accept whatever your GRC system uses (`RCTL-043`, `peer-review`, `vuln-scan-production`)? |
| 179 | +- **Catalog sync.** Should Kosli pull from your GRC system, or is a one-way mirror managed via CLI/API enough? |
| 180 | +- **Versioning behavior.** Decisions would reference the control version current at decision time. Is that the right default, or should the latest version always win for reporting? |
| 181 | +- **Coverage windows.** "Active" within 28 days - is that the right window, or should it be configurable per control? |
| 182 | +- **Policy gating.** Should missing decisions block deployments by default, or only when explicitly asserted via `kosli assert`? |
| 183 | + |
| 184 | +Tell us what you think - email [support@kosli.com](mailto:support@kosli.com). |
0 commit comments