Conversation
|
I should make it clear that this is draft specifically because it includes changes to CLAUDE.md and claude settings. |
There was a problem hiding this comment.
Pull request overview
Adds a new kosli evaluate CLI command family that evaluates trail data locally against embedded OPA/Rego policies, including a client-side enrichment pipeline to make trail/attestation data policy-friendly.
Changes:
- Introduce
kosli evaluate trailandkosli evaluate trailscommands with--policy,--output json|table,--show-input, and--attestations. - Add
internal/evaluatepackage for Rego evaluation plus transform/filter/rehydrate trail-data enrichment. - Upgrade and add Go module dependencies (notably embedding
github.com/open-policy-agent/opaand bumping several libs, includinggolang.org/x/net).
Reviewed changes
Copilot reviewed 28 out of 29 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/evaluate/transform.go | Implements trail enrichment (array→map transform, filtering, ID collection, rehydration). |
| internal/evaluate/transform_test.go | Unit tests for enrichment pipeline stages and edge cases. |
| internal/evaluate/rego.go | OPA/Rego evaluation wrapper (Evaluate, policy validation, violations collection). |
| internal/evaluate/rego_test.go | Unit tests for basic allow/deny and policy validation errors. |
| cmd/kosli/evaluate.go | Adds evaluate parent command and wires subcommands. |
| cmd/kosli/evaluateTrail.go | Implements kosli evaluate trail command wrapper and input shape (input.trail). |
| cmd/kosli/evaluateTrails.go | Implements kosli evaluate trails command wrapper and input shape (input.trails). |
| cmd/kosli/evaluateHelpers.go | Shared flag registration, fetch+enrich pipeline, and output dispatch for evaluate commands. |
| cmd/kosli/evaluateTrail_test.go | Integration-style command tests for evaluate trail behavior, output, enrichment, filtering, and rehydration errors. |
| cmd/kosli/evaluateTrails_test.go | Integration-style command tests for evaluate trails behavior, output, and enrichment/rehydration/filtering. |
| cmd/kosli/root.go | Registers evaluate on the root command. |
| cmd/kosli/testHelpers.go | Adds goldenJsonContains support for asserting a JSON path value is non-nil. |
| cmd/kosli/testdata/policies/allow-all.rego | Test policy fixture: always allow. |
| cmd/kosli/testdata/policies/deny-all.rego | Test policy fixture: always deny with a violation. |
| cmd/kosli/testdata/policies/invalid.rego | Test policy fixture: invalid Rego syntax. |
| cmd/kosli/testdata/policies/check-attestation-name.rego | Fixture asserting transformed trail-level attestation map access for single-trail mode. |
| cmd/kosli/testdata/policies/check-filtered-attestation.rego | Fixture asserting --attestations filtering for single-trail mode. |
| cmd/kosli/testdata/policies/check-rehydrated-field.rego | Fixture asserting rehydrated field presence for single-trail mode. |
| cmd/kosli/testdata/policies/check-trails-attestation-name.rego | Fixture asserting transformed trail-level attestation map access for multi-trail mode. |
| cmd/kosli/testdata/policies/check-trails-filtered-attestation.rego | Fixture asserting --attestations filtering for multi-trail mode. |
| cmd/kosli/testdata/policies/check-trails-rehydrated-field.rego | Fixture asserting rehydrated field presence for multi-trail mode. |
| docs/adr/20260302-client-side-policy-evaluation.md | ADR documenting rationale for client-side embedded OPA/Rego evaluation. |
| docs/adr/20260302-client-side-enrichment-pipeline.md | ADR documenting transform/filter/rehydrate enrichment pipeline and trade-offs. |
| docs.kosli.com/content/tutorials/evaluate_trails_with_opa.md | Draft tutorial for using kosli evaluate with example Rego policies. |
| go.mod | Adds OPA dependency and updates multiple module versions. |
| go.sum | Updates dependency checksums to match go.mod changes. |
| TODO.md | Adds a slice/TDD checklist for the feature (currently committed into repo). |
| CLAUDE.md | Updates Claude workflow guidance (now allows git checkout/add/commit; still forbids push). |
| .claude/settings.json | Updates allowed/denied bash command patterns for Claude tooling (allows checkout/add/commit; still denies push). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Slice 1 of kosli evaluate trail - adds the evaluate parent command
and evaluate trail subcommand that fetches a trail from the API and
wraps the response in {"trail": ...} JSON output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds internal/evaluate with Evaluate() function that validates and evaluates Rego policies. Validates package name is 'policy', requires an 'allow' rule, collects violations on deny. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds --policy flag to evaluate trail command. Reads a .rego file, evaluates it against the trail input using OPA, exits 0 on allow and 1 on deny. Uses Rego v1 syntax. Policy must use package policy and declare an allow rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e and violations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…wed text Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…violations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests: non-map passthrough, no compliance_status passthrough, empty array to empty map, single attestation keyed by name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests: multiple trail attestations, artifact-level, both levels, multiple artifacts, entries without attestation_name skipped. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…maps Wire TransformTrail into evaluateTrail after JSON parse. Tests verify trail-level and artifact-level maps, plus Rego policy access by name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Great work @tooky Looking at Shouldn't this be tracked as a slice in
|
Why is "human readable" the default? |
Claude response: One more design observation worth capturing before this merges. Policies are currently fully static. Thresholds like "zero approvers" or "no critical vulnerabilities" are baked into the Is adding parameter support later a breaking change? Not with the current implementation. OPA has a first-class What it could look like: Policy: package policy
import rego.v1
default min_approvers := 1
min_approvers := input.params.min_approvers if {
input.params.min_approvers
}
violations contains msg if {
some trail in input.trails
some pr in trail.compliance_status.attestations_statuses["pull-request"].pull_requests
count(pr.approvers) < min_approvers
msg := sprintf("trail '%v': PR %v has only %d approver(s), need %d", [trail.name, pr.url, count(pr.approvers), min_approvers])
}
allow if { count(violations) == 0 }CLI: $ kosli evaluate trails \
--policy pr-approved.rego \
--params '{"min_approvers": 2}' \
--flow server \
...As a next increment: A Worth tracking in |
Claude response: The two-command design creates a policy portability problem that's worth collapsing before this merges.
The consequences:
The divergence is in two lines of code — Collapsing to just
The only thing lost is the grammatical nicety of |
Claude response:
OPA does have an # METADATA
# entrypoint: true
allow if { ... }But that annotation is primarily for The current code enforces That makes it worth being explicit about in the CLI docs and examples, rather than assuming users will know. |
|
Same goes for One difference worth noting: |
|
@dangrondahl yes more CLI docs would be good!
I would be super interested to see how cluade would work for others doing something like this wtht eh claude.md here |
That's the convention for the CLI |
I only see: in CLAUDE.md Also, I assumed that it checked it surroundings a bit more and saw "neighbouring" commands docs, when creating a new one. That has been my experience in e.g. the Terraform provider. |
Good challenge. Interesting question. I started here as a deliberate design decision - I was thinking of 2 types of use case.
I wasn't imagining that those policies for a single trail, would necessarily be portable to evaluate a number of trails. Maybe, that's not the case. The other thing in my head is that if I know I am evaluating a single trail then I don't want to have a list, I'm specifcally dealing with 1, or 0 is an error. If I expect a list, then empty list is valid. |
|
On E,g.
It means we can provide some of the boiler plate. I think we might want escape hatches though. |
Yes, this is an extension that we should consider. I want to be mindful of where this lives though. Eventually I see evaluation and policy being server side in Kosli, and we might not want to parameterisation to be sent in from the client - it might need to be more controlled. I would favour holding off on this for now. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 29 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ual-command example with snyk trail example Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ual-command example with snyk trail example Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* add Long descriptions and Example blocks to evaluate commands * address PR #671 docs feedback: * expand policy contract hint * replace dual-command example with snyk trail example * publish evaluate trails tutorial (remove draft status)
Why: Customers are duplicating attestation types to work around the lack of evaluation logic — creating separate types per environment just to encode different pass/fail rules. Three independent customers have hit this, and two more are building toward it. This is the most consistent product gap in our pipeline.
Objective: Add
kosli evaluate— a CLI command that applies a Rego policy to trail data and returns a structured pass/fail decision. This separates what you collect (attestation type) from how you judge it (evaluation), and is the first step toward controls as a first-class product concept.How this was built
This PR is also a demonstration of elephant carpaccio + TDD with Claude Code. The entire feature was built as a conversation — 48 commits, each one a single red-green-refactor step. Slices were kept thin enough to review independently, and the commit list reads bottom-to-top as a narrative of how the feature grew. Later commits came from reviewing the branch against Beck's Rules of Simple Design. The branch is intentionally unrebased so you can follow the progression.
Capabilities
kosli evaluate trail <name>— single trail against a Rego policykosli evaluate trails <name>...— multiple trails in one policy call--output json|table— structured audit output or human-readable (default)--show-input— include policy input in JSON output for debugging--attestations— filter which attestations reach the policy (plain name for trail-level,artifact.namefor artifact-level)Example
Validate all PRs are approved:
Kosli Server:
CyberDojo Dashboard:
Architecture
internal/evaluate/— OPA Rego engine + trail data transforms (array-to-map, rehydration from detail API, filtering)cmd/kosli/evaluateHelpers.go— shared options, flag registration, fetch+enrich pipeline, output dispatchcmd/kosli/evaluateTrail.go/evaluateTrails.go— thin command wrappersAlso included
golang.org/x/netto v0.51.0 for CVE-2026-27141