Skip to content

Engine-injected project context for chainloop.* built-ins #3090

@migmartri

Description

@migmartri

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

  1. Make chainloop.findings callable from material-kind policies without the rego author writing project context.
  2. Establish a single, reusable convention so future chainloop.* built-ins inherit the same behaviour.
  3. 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:

  1. 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.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions