presets

package
v2.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

View Source
const PromotionCooldown = 14 * 24 * time.Hour

PromotionCooldown is how long a newly published version must have been publicly available before the catalogue promotes it. The monitor runs weekly, so this is roughly two cycles.

It is deliberately not a user-facing setting: the policy governs cidx's own catalogue, not the projects that use cidx, which pin whatever they want in their own cidx.toml (guardrail 5). Shortening the window is a decision to argue for in a commit, not to bury in a config file.

Variables

View Source
var GlobalRegistry map[string]Preset

GlobalRegistry contains all built-in presets Loaded from presets.yaml (dev) or embedded data (production)

Functions

func Exists

func Exists(name string) bool

Exists checks if a preset exists

func GroupByPhase

func GroupByPhase() map[string][]string

GroupByPhase returns presets grouped by phase

func IsCustomDeclaration

func IsCustomDeclaration(overrides map[string]any) bool

IsCustomDeclaration reports whether the given override section declares a brand-new container (image field present) rather than overriding an existing preset. Used by validator and runner to decide between preset-override semantics and custom-container semantics.

func List

func List() []string

List returns all preset names

func ListByPhase

func ListByPhase(phase string) []string

ListByPhase returns presets filtered by phase

func NewerTag added in v2.3.0

func NewerTag(currentTag string, available []string) string

NewerTag returns the newest tag in available that is a strictly newer version of currentTag, or "" when nothing on offer qualifies.

Qualifying means the same shape as the tag the catalogue already pins:

  • Same variant family — same `v` prefix, same suffix after the version. `dhi.io/golang:1.23-alpine3.21-dev` must never be offered a plain `1.24`: that is a different image on a different base, and promoting it would silently change what every Go preset runs on. The same guard keeps `-dev`, `-fips`, `-cli` and `-alpine` variants in their own lane.

  • Same precision. A registry publishing `0.71` and `0.71.2` offers the first to an image pinned `0.68` and the second to one pinned `0.68.1`. The number of components is a choice the catalogue made about how closely it tracks upstream, and an update is not the place to revisit it.

A currentTag carrying no version (`latest`) qualifies nothing: there is no way to tell what would be newer, and claiming an update would be a guess.

Types

type Option

type Option struct {
	Type        string `yaml:"type" toml:"type"`                 // string, bool, int, array
	Default     any    `yaml:"default" toml:"default"`           // Default value
	Description string `yaml:"description" toml:"description"`   // Help text
	EnvVar      string `yaml:"env_var" toml:"env_var"`           // Maps to environment variable
	CommandFlag string `yaml:"command_flag" toml:"command_flag"` // Maps to command flag
}

Option defines a configurable parameter for a preset

type OptionTOML

type OptionTOML struct {
	Type        string      `toml:"type"`
	Default     interface{} `toml:"default"`
	Description string      `toml:"description"`
	CommandFlag string      `toml:"command_flag"`
	EnvVar      string      `toml:"env_var"`
}

OptionTOML represents an option in TOML format

type Preset

type Preset struct {
	Name          string            `yaml:"name" toml:"name"`
	Phase         string            `yaml:"phase" toml:"phase"`
	Image         string            `yaml:"image" toml:"image"`
	Description   string            `yaml:"description,omitempty" toml:"description,omitempty"` // Usage notes and constraints, shown by `preset info`
	Hardened      bool              `yaml:"hardened,omitempty" toml:"hardened,omitempty"`       // Uses Docker Hardened Image (dhi.io)
	Command       string            `yaml:"command" toml:"command"`
	Entrypoint    []string          `yaml:"entrypoint" toml:"entrypoint"`
	Workdir       string            `yaml:"workdir" toml:"workdir"`
	Volumes       []string          `yaml:"volumes" toml:"volumes"`
	Env           map[string]string `yaml:"env" toml:"env"`
	ConfigFiles   []string          `yaml:"config_files" toml:"config_files"`
	Options       map[string]Option `yaml:"options" toml:"options"`
	RequireCI     bool              `yaml:"require_ci" toml:"require_ci"`                       // Requires CI environment
	LocalBehavior string            `yaml:"local_behavior" toml:"local_behavior"`               // draft, no-push, dry-run, disabled
	Privileged    bool              `yaml:"privileged,omitempty" toml:"privileged,omitempty"`   // Requires root privileges (skip user mapping)
	PullPolicy    string            `yaml:"pull_policy,omitempty" toml:"pull_policy,omitempty"` // always, if-not-present, never (default: env-based)
	Timeout       string            `yaml:"timeout,omitempty" toml:"timeout,omitempty"`         // duration string (e.g., "5m", "45m"), default: 30m
}

Preset defines a complete tool configuration with sensible defaults

func Get

func Get(name string) (Preset, error)

Get retrieves a preset by name

func PresetFromOverrides

func PresetFromOverrides(name string, overrides map[string]any) Preset

PresetFromOverrides constructs a Preset from a custom container declaration in cidx.toml. A declaration is a `[containers.NAME]` section that has an `image` field present — that signals a brand-new container, not an override of a known preset. The returned Preset is filled from the overrides map; fields absent from the map keep their zero value.

This implements the user-facing contract documented in examples/cidx-complete.toml (custom containers section) and closes #142.

func (*Preset) MergeWith

func (p *Preset) MergeWith(overrides map[string]any) *Preset

MergeWith merges user overrides into the preset

type PresetTOML

type PresetTOML struct {
	Name          string                `toml:"name"`
	Phase         string                `toml:"phase"`
	Image         string                `toml:"image"`
	Description   string                `toml:"description"`
	Hardened      bool                  `toml:"hardened"`
	Command       string                `toml:"command"`
	Entrypoint    []string              `toml:"entrypoint"`
	Workdir       string                `toml:"workdir"`
	Volumes       []string              `toml:"volumes"`
	Env           map[string]string     `toml:"env"`
	ConfigFiles   []string              `toml:"config_files"`
	Options       map[string]OptionTOML `toml:"options"`
	RequireCI     bool                  `toml:"require_ci"`
	LocalBehavior string                `toml:"local_behavior"`
	Privileged    bool                  `toml:"privileged"`
	PullPolicy    string                `toml:"pull_policy"`
	Timeout       string                `toml:"timeout"`
}

PresetTOML represents a preset in TOML format

type PresetsFile

type PresetsFile struct {
	Presets map[string]PresetTOML `toml:"presets"`
}

PresetsFile represents the structure of presets.toml

type PromotionDecision added in v2.2.0

type PromotionDecision struct {
	// Promote reports whether the candidate may replace the running image.
	Promote bool

	// Reason states why. Always set, for promotions as much as for holds — a
	// candidate held for another week has to say so somewhere, or the policy
	// silently swallows it.
	Reason string

	// WaivedFor names the vulnerabilities that bought the candidate its way
	// past the cooldown. Empty when no waiver was needed, so a promotion never
	// claims a waiver that did nothing.
	WaivedFor []string

	// AgeDays is how long the candidate has been public, in whole days. Nil
	// when the registry gave no date.
	AgeDays *int
}

PromotionDecision is the verdict on one candidate version, in the words the workflow summary and the promotion PR print verbatim.

func EvaluatePromotion added in v2.2.0

func EvaluatePromotion(published, now time.Time, affectingUs []string) PromotionDecision

EvaluatePromotion applies the cooldown and its exception to one candidate.

published is when the candidate became publicly available; the zero time means the registry would not say. affectingUs are the HIGH/CRITICAL vulnerabilities already recorded against the image the catalogue runs today.

An undatable candidate is held. That mirrors rule 1's treatment of an unresolvable digest: the promotion is skipped rather than taken on an assumption, and the reason is reported so it does not vanish quietly.

The exception then overrides the hold — for a young candidate and an undatable one alike. Waiting out a date that will never arrive would just leave a known vulnerability in place, and deliberately running a known-vulnerable image to guard against a hypothetical one is the worse trade. A candidate that has served the cooldown claims no waiver: it did not need one.

type ScanDecision added in v2.3.0

type ScanDecision struct {
	// Promote reports whether the findings leave the candidate promotable.
	Promote bool

	// Reason states why — for a pass as much as for a hold. A candidate the
	// scan gate holds has to say so somewhere, or the promotion silently
	// swallows it, which is the failure mode #247 was about in the first place.
	Reason string

	// Introduces names the findings that blocked the promotion: on the
	// candidate, on neither the running image's record nor the candidate's own,
	// and therefore new. Empty on a pass, so a promotion never implies findings
	// it does not have.
	Introduces []string
}

ScanDecision is the verdict on what the monitor's scanners found on one candidate, in the words the workflow summary and the promotion PR print verbatim.

func EvaluateScan added in v2.3.0

func EvaluateScan(found, accepted []string) ScanDecision

EvaluateScan decides whether what the scanners found on a candidate blocks its promotion.

found are the HIGH/CRITICAL vulnerabilities the monitor's scanners reported against the candidate. accepted are the ones already on record for the image the catalogue runs today and for the candidate's own reference (known-vulnerabilities.toml, the file the security audit maintains).

The verdict is differential on purpose. Several catalogue images are knowingly vulnerable — that is exactly what known-vulnerabilities.toml records — so "the candidate has findings" would hold every one of them for ever, and a gate that never passes is worth as little as the one that never failed (#247). What blocks a promotion is a finding that is *new*: reported on the candidate, not already accepted on what we run today.

It follows that a candidate carrying the same vulnerabilities as the running image is promotable. It is not a regression, and refusing it would strand the catalogue on an older image over a finding the candidate merely inherited — while the update it carries goes unapplied.

Comparison is case-insensitive: Trivy spells severities and identifiers in upper case, Grype does not, and the same CVE reported by both must count once.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL