Context
chainloop.findings (and its sibling chainloop.project_compliance) require project_name and project_version_name as request fields. This is incompatible with material-kind policies (vulnerability policies, SAST, etc.), whose input is the parsed material with no project metadata anywhere — there is no way for a rego author to populate those fields, so policies fail to type-check at evaluation time:
rego_type_error: chainloop.findings: invalid argument(s)
have: (object<finding_type: array<string>, status: array<string>>, ???)
want: (request: object<
finding_type, status, severity: any<string, array[string]>,
project_name: string,
project_version_name: string,
>, response: array[any])
As a result, vulnerability policies that should be calling chainloop.findings (to suppress assessed findings) cannot, and any future built-in that needs project scope hits the same wall.
Goals
- Make
chainloop.findings callable from material-kind policies without the rego author writing project context.
- Establish a single, reusable convention so future
chainloop.* built-ins inherit the same behaviour.
- Keep
chainloop.project_compliance working unchanged for check-compliance-requirement (no migration churn for attestation-kind policies).
Non-Goals
- Changing how attestation-kind policies receive project context (
input.predicate.metadata.project keeps working).
- Exposing project context to user policies as readable input fields. Engine-side injection only.
- Designing how server-side rego evaluation gets the same context (tracked separately).
Proposed Approach
The CLI's policy engine maintains a per-evaluation context with the project name and version it is currently attesting against. When a chainloop.* built-in is invoked, the engine fills in project_name and project_version_name on the request before OPA type-checking runs.
Two separate problems to solve:
- Type-check time — OPA validates built-in argument types at compile time. Required fields make the policy fail to compile if absent. Mark
project_name and project_version_name optional in the built-in's declared schema.
- Runtime — When the built-in is invoked without project context, the engine fills it in from the per-evaluation context. Author-provided values still win.
Engine context plumbing
Add per-evaluation project name/version fields to the rego engine options. The attestation crafter populates them at evaluation start (it already knows project + version from the run config). For chainloop policy develop eval, populate from new optional --project / --project-version flags, or leave empty.
Surface the values to built-ins via bctx.Context so any built-in (including EE-only) can pull them from the per-evaluation context.
Built-in schema relaxation + runtime fill-in
Mark project_name / project_version_name optional in the built-in schemas. In the Go implementation:
if req.ProjectName == "" {
req.ProjectName = engineCtx.ProjectName
}
if req.ProjectVersionName == "" {
req.ProjectVersionName = engineCtx.ProjectVersionName
}
if req.ProjectName == "" || req.ProjectVersionName == "" {
return emptyList, nil // graceful degradation for local dev
}
Same change to chainloop.project_compliance.
Local dev experience
chainloop policy develop eval gains optional --project / --project-version flags. When omitted, built-ins return empty results so the rego author can still iterate locally; suppression simply never fires.
Graceful failure on entitlement / network errors
connect.CodeFailedPrecondition / Unauthenticated from the platform should not kill the whole policy. Built-ins log and return an empty list rather than erroring.
Risks
- Schema relaxation could break
check-compliance-requirement (still passes the fields explicitly) — mitigated because author-provided values win.
- Local dev eval silently produces no suppression and dev assumes feature is broken — mitigate with a debug log line and clear flag documentation.
- Entitlement-error fall-through hiding a real outage — match on specific connect codes only.
Related
- Spec 051 (Allow-list Vulnerabilities via Risk Assessments) is blocked on this.
Context
chainloop.findings(and its siblingchainloop.project_compliance) requireproject_nameandproject_version_nameas request fields. This is incompatible with material-kind policies (vulnerability policies, SAST, etc.), whoseinputis the parsed material with no project metadata anywhere — there is no way for a rego author to populate those fields, so policies fail to type-check at evaluation time:As a result, vulnerability policies that should be calling
chainloop.findings(to suppress assessed findings) cannot, and any future built-in that needs project scope hits the same wall.chainloop.findingscallable from material-kind policies without the rego author writing project context.chainloop.*built-ins inherit the same behaviour.chainloop.project_complianceworking unchanged forcheck-compliance-requirement(no migration churn for attestation-kind policies).Non-Goals
input.predicate.metadata.projectkeeps working).Proposed Approach
The CLI's policy engine maintains a per-evaluation context with the project name and version it is currently attesting against. When a
chainloop.*built-in is invoked, the engine fills inproject_nameandproject_version_nameon the request before OPA type-checking runs.Two separate problems to solve:
project_nameandproject_version_nameoptional in the built-in's declared schema.Engine context plumbing
Add per-evaluation project name/version fields to the rego engine options. The attestation crafter populates them at evaluation start (it already knows project + version from the run config). For
chainloop policy develop eval, populate from new optional--project/--project-versionflags, or leave empty.Surface the values to built-ins via
bctx.Contextso any built-in (including EE-only) can pull them from the per-evaluation context.Built-in schema relaxation + runtime fill-in
Mark
project_name/project_version_nameoptional in the built-in schemas. In the Go implementation:Same change to
chainloop.project_compliance.Local dev experience
chainloop policy develop evalgains optional--project/--project-versionflags. When omitted, built-ins return empty results so the rego author can still iterate locally; suppression simply never fires.Graceful failure on entitlement / network errors
connect.CodeFailedPrecondition/Unauthenticatedfrom the platform should not kill the whole policy. Built-ins log and return an empty list rather than erroring.Risks
check-compliance-requirement(still passes the fields explicitly) — mitigated because author-provided values win.Related