discovery

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: AGPL-3.0, AGPL-3.0-only Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Discover

func Discover(ctx context.Context, opts map[string]any, files []lint.FileInfo) (*supplychain.Snapshot, error)

Discover runs the full dependency resolution pipeline once and returns an immutable supplychain.Snapshot. It is the single public Snapshot producer — callers that need ONE resolution pass shared across multiple consumers (e.g. the audition pipeline, which threads the Snapshot to both the freshness lint module and the dependency-update step) call Discover exactly once and pass the result down explicitly. Resolve remains the entry point for standalone callers (e.g. `stagefreight dependency update`) that don't need a shared Snapshot; Discover wraps it so both stay in sync.

func Resolve

func Resolve(ctx context.Context, opts map[string]any, files []lint.FileInfo) ([]supplychain.Dependency, error)

Resolve runs the full dependency resolution pipeline across all files and returns raw Dependency structs with vulnerabilities correlated. opts is passed to Configure; nil uses FreshnessConfig defaults.

func SplitImageNamespace

func SplitImageNamespace(image string) (string, string)

SplitImageNamespace splits an image name into (namespace, repo) for Docker Hub. "golang" → ("library", "golang") "prplanit/stagefreight" → ("prplanit", "stagefreight") "ghcr.io/owner/repo" → not Docker Hub, skip.

func SplitImageTag

func SplitImageTag(ref string) (string, string)

SplitImageTag splits "golang:1.25-alpine" into ("golang", "1.25-alpine").

Types

type FreshnessConfig

type FreshnessConfig struct {
	Sources       SourceConfig   `json:"sources"`
	Severity      SeverityConfig `json:"severity"`
	Vulnerability VulnConfig     `json:"vulnerability"`
	Registries    RegistryConfig `json:"registries"`
	Ignore        []string       `json:"ignore"`
	PackageRules  []PackageRule  `json:"package_rules"`
	Groups        []Group        `json:"groups"`
	Timeout       int            `json:"timeout"`   // HTTP timeout in seconds (default 10)
	CacheTTLSecs  int            `json:"cache_ttl"` // cache TTL in seconds (default 300; 0 = cache forever; <0 = never cache)

	// MinReleaseAge is a supply-chain cooldown: freshness will not recommend (and so
	// stagefreight will not auto-adopt) a release published more recently than this window.
	// Most malicious npm publishes — compromised maintainer tokens, typosquats — are caught
	// and yanked within hours to days, so a cooldown sidesteps that exposure window. Accepts
	// "7d", "2w", "72h", or any Go duration. Empty/0 = disabled. Implemented for npm (the
	// registry exposes per-version publish times); other ecosystems ignore it until wired.
	MinReleaseAge string `json:"min_release_age"`

	// FetchVersionLists is a capability flag (NOT a policy): when set, resolvers that
	// would otherwise fetch only the latest version also retrieve the full published
	// version list into Dependency.AvailableVersions. The deps layer enables it solely
	// under a patch-lock ceiling — the only case that re-targets to a lower in-range
	// version and thus needs the list — so the default path pays no extra network. A
	// resolver that already has the list for free (cargo) populates it regardless.
	FetchVersionLists bool `json:"fetch_version_lists"`
}

FreshnessConfig holds per-source toggles, severity mapping, package rules, registry overrides, vulnerability correlation, and grouping configuration.

func DefaultConfig

func DefaultConfig() FreshnessConfig

DefaultConfig returns production defaults.

func (*FreshnessConfig) CacheTTL

func (c *FreshnessConfig) CacheTTL() time.Duration

CacheTTL returns the cache TTL as a time.Duration.

  • >0 → cache with expiry (e.g. 300 → 5m)
  • 0 → cache forever (content-hash only)
  • <0 → never cache (always re-run)

func (*FreshnessConfig) EffectiveSeverity

func (c *FreshnessConfig) EffectiveSeverity(dep supplychain.Dependency, updateType string) SeverityConfig

EffectiveSeverity returns the severity config for a dependency, checking packageRules first, then falling back to the global config.

func (*FreshnessConfig) GroupForDep

func (c *FreshnessConfig) GroupForDep(dep supplychain.Dependency, updateType string) string

GroupForDep returns the group name assigned by a matching package rule.

func (*FreshnessConfig) IsDisabledByRule

func (c *FreshnessConfig) IsDisabledByRule(dep supplychain.Dependency) bool

IsDisabledByRule checks if a package rule explicitly disables this dep.

func (*FreshnessConfig) IsIgnored

func (c *FreshnessConfig) IsIgnored(name string) bool

IsIgnored returns true if name matches any ignore glob or a package rule disables it.

func (*FreshnessConfig) SourceEnabled

func (c *FreshnessConfig) SourceEnabled(ecosystem string) bool

SourceEnabled checks whether a particular ecosystem is turned on.

func (*FreshnessConfig) VulnSeverityOverride

func (c *FreshnessConfig) VulnSeverityOverride() bool

VulnSeverityOverride returns whether CVE-affected deps should be escalated to critical regardless of version delta.

type Group

type Group struct {
	Name                string `json:"name"`
	CommitMessagePrefix string `json:"commit_message_prefix"`
	Automerge           *bool  `json:"automerge"`      // group-level automerge default
	SeparateMajor       bool   `json:"separate_major"` // split major bumps into own MR
}

Group configures how matched dependencies are batched together for future MR creation. Reserved in config shape now; the MR engine will consume these when update mode is implemented.

.stagefreight.yml example:

groups:
  - name: "go-patch-updates"
    commit_message_prefix: "deps(go): "
    automerge: true
  - name: "docker-base-images"
    separate_major: true

type PackageRule

type PackageRule struct {
	// Pattern matching — all specified fields must match (AND logic).
	MatchPackages      []string `json:"match_packages"`      // glob patterns on dependency name
	MatchEcosystems    []string `json:"match_ecosystems"`    // ecosystem constants (docker-image, gomod, etc.)
	MatchUpdateTypes   []string `json:"match_update_types"`  // "major", "minor", "patch"
	MatchVulnerability *bool    `json:"match_vulnerability"` // true = only match deps with known CVEs

	// Overrides applied when matched.
	Enabled  *bool           `json:"enabled"`  // false = skip this dependency entirely
	Severity *SeverityConfig `json:"severity"` // override severity/tolerance for matched deps
	Group    string          `json:"group"`    // assign to a named group (for future MR batching)

	// Future update-mode fields (wired later, config-shape reserved now).
	Automerge *bool `json:"automerge"` // auto-merge MR if CI passes
}

PackageRule overrides severity, tolerance, or behaviour for dependencies that match its patterns. Rules are evaluated in order; first match wins. Modeled after Renovate's packageRules.

.stagefreight.yml example:

package_rules:
  - match_packages: ["golang", "alpine"]
    severity: { major: 2, minor: 2, patch: 1 }
  - match_packages: ["*.test", "mock-*"]
    enabled: false
  - match_ecosystems: ["gomod"]
    match_update_types: ["patch"]
    automerge: true
    group: "go-patch-updates"

type RegistryConfig

type RegistryConfig struct {
	Docker *RegistryEndpoint `json:"docker"`
	Go     *RegistryEndpoint `json:"go"`
	Npm    *RegistryEndpoint `json:"npm"`
	PyPI   *RegistryEndpoint `json:"pypi"`
	Crates *RegistryEndpoint `json:"crates"`
	Alpine *RegistryEndpoint `json:"alpine"`
	Debian *RegistryEndpoint `json:"debian"`
	Ubuntu *RegistryEndpoint `json:"ubuntu"`
	GitHub *RegistryEndpoint `json:"github"` // GitHub API for tool version checks
}

RegistryConfig overrides the default public registry URLs per ecosystem. Each field accepts a RegistryEndpoint; if URL is empty the public default is used. Auth is resolved from environment variables at runtime.

.stagefreight.yml example:

registries:
  docker:
    url: "https://jcr.pcfae.com/v2"
    auth_env: "JCR_TOKEN"
  go:
    url: "https://goproxy.company.com"
  npm:
    url: "https://npm.company.com"
    auth_env: "NPM_TOKEN"

type RegistryEndpoint

type RegistryEndpoint struct {
	URL     string `json:"url"`      // base URL (e.g. "https://jcr.pcfae.com/v2")
	AuthEnv string `json:"auth_env"` // env var name holding auth token (Bearer)
}

RegistryEndpoint is a custom registry URL with optional auth.

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver runs the dependency-resolution engine: per-ecosystem checkers, registry lookups, and vulnerability correlation. It holds no lint dependency beyond lint.FileInfo, the resolver input type.

func NewResolver

func NewResolver() *Resolver

NewResolver constructs a Resolver with default configuration.

func (*Resolver) Config

func (m *Resolver) Config() *FreshnessConfig

Config returns the resolver's active configuration.

func (*Resolver) Configure

func (m *Resolver) Configure(opts map[string]any) error

Configure applies the parsed FreshnessConfig options.

func (*Resolver) FetchManifestDigest

func (m *Resolver) FetchManifestDigest(ctx context.Context, image, tag string) (string, error)

FetchManifestDigest queries the registry v2 manifest endpoint for the digest of image:tag. Used by the freshness renderer's digest-lock check for non-versioned tags (e.g. "latest", "noble").

func (*Resolver) ResolveFile

func (m *Resolver) ResolveFile(ctx context.Context, file lint.FileInfo) ([]supplychain.Dependency, error)

ResolveFile resolves dependencies for a single file using the Resolver's current configuration, correlating vulnerabilities. Lazily initializes the HTTP client if Configure was not called (defaults). This is the entry point used by the freshness lint renderer's per-file Check.

func (*Resolver) SetToolchainDesired

func (m *Resolver) SetToolchainDesired(desired map[string]config.ToolConstraint)

SetToolchainDesired records the toolchains.desired config used by checkToolchainDesired.

type SeverityConfig

type SeverityConfig struct {
	Major int `json:"major"` // 0=info, 1=warning, 2=critical (default: 2)
	Minor int `json:"minor"` // default: 1
	Patch int `json:"patch"` // default: 0

	MajorTolerance int `json:"major_tolerance"` // default: 0
	MinorTolerance int `json:"minor_tolerance"` // default: 0
	PatchTolerance int `json:"patch_tolerance"` // default: 1
}

SeverityConfig maps version-delta levels to lint severities and controls how many versions behind are tolerated before reporting.

type SourceConfig

type SourceConfig struct {
	DockerImages   *bool `json:"docker_images"`
	GitHubReleases *bool `json:"github_releases"`
	GoModules      *bool `json:"go_modules"`
	RustCrates     *bool `json:"rust_crates"`
	NpmPackages    *bool `json:"npm_packages"`
	AlpineAPK      *bool `json:"alpine_apk"`
	DebianAPT      *bool `json:"debian_apt"`
	PipPackages    *bool `json:"pip_packages"`
}

SourceConfig toggles individual dependency ecosystems on or off. nil means "use default" (true for all).

type VulnConfig

type VulnConfig struct {
	Enabled          *bool  `json:"enabled"`           // default true
	MinSeverity      string `json:"min_severity"`      // "low", "moderate", "high", "critical" (default: "moderate")
	SeverityOverride *bool  `json:"severity_override"` // CVE-affected deps escalate to critical (default: true)
}

VulnConfig controls vulnerability correlation via the OSV database.

.stagefreight.yml example:

vulnerability:
  enabled: true
  min_severity: "moderate"
  severity_override: true

Jump to

Keyboard shortcuts

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