Documentation
¶
Index ¶
- Constants
- func AllLicenses() map[string]LicenseRecord
- func BatchFetchGitHubLicenses(packages []PackageLicense, onProgress func(resolved, total int))
- func BatchFetchLicenses(packages []PackageLicense, onProgress func(resolved, total int))
- func BatchFetchRegistryLicenses(packages []PackageLicense, onProgress func(resolved, total int))
- func BuildSARIFFromAnalysis(result *AnalysisResult) ([]SARIFFinding, []SARIFRule)
- func CanonicalSPDXID(id string) string
- func ClassifyLicenseText(text string) string
- func ConflictFindingID(c LicenseConflict) string
- func CountFindingsAtOrAbove(findings []Finding, threshold string) int
- func FetchContainerLicense(name, version, ecosystem string) string
- func FetchFromEcosystemRegistry(pkg PackageLicense) string
- func FetchLicenseFromDepsDev(name, version, ecosystem string) string
- func FetchLicenseFromGitHub(name, ecosystem string) string
- func FindLicenseInDir(dir string) string
- func FindLicenseInModuleCache(moduleName, version string) string
- func FindingID(category string, pkg PackageLicense) string
- func FindingsToCDXVulnerabilities(findings []Finding, packages []PackageLicense) []cdx.Vulnerability
- func MarshalSPDXJSON(doc *SPDXDocument) ([]byte, error)
- func MergeBOM(existingPath string, newVulns []cdx.Vulnerability, source string) error
- func NormalizeSPDX(id string) string
- func ParseSPDXExpression(expr string) []string
- func PopulateBOMLicenses(bomPath string, packages []PackageLicense, groups []scan.ManifestGroup)
- type AllowList
- type AnalysisResult
- type AnalysisSummary
- type Applied
- type BlanketException
- type Category
- type ConflictSeverity
- type EvalConfig
- type EvidenceStep
- type Exception
- type ExceptionSet
- type Finding
- type LicenseConflict
- type LicenseRecord
- type PackageException
- type PackageLicense
- type Policy
- func (p *Policy) CategoryFor(spdxID string, fallback Category) Category
- func (p *Policy) EvaluatesScope(scope, project string) bool
- func (p *Policy) MarshalYAML() ([]byte, error)
- func (p *Policy) SeverityFor(cat Category, project string) string
- func (p *Policy) UnknownFor(project string) UnknownHandling
- func (p *Policy) Validate() error
- type ProjectPolicy
- type RepoLicenseHit
- type SARIFFinding
- type SARIFRule
- type SPDXChecksum
- type SPDXCreationInfo
- type SPDXDocument
- type SPDXExternalRef
- type SPDXExtractedLicense
- type SPDXPackage
- type SPDXRelationship
- type ScopeHandling
- type UnknownHandling
Constants ¶
const CDXSourceName = "vulnetix-license-analyzer"
const ExceptionsAPIVersion = "vulnetix.com/v1"
ExceptionsAPIVersion is the apiVersion an exceptions document must declare.
const ExceptionsKind = "LicenseExceptions"
ExceptionsKind is the kind an exceptions document must declare.
const PolicyAPIVersion = "vulnetix.com/v1"
PolicyAPIVersion is the apiVersion a policy document must declare.
const PolicyKind = "LicensePolicy"
PolicyKind is the kind a policy document must declare.
Variables ¶
This section is empty.
Functions ¶
func AllLicenses ¶
func AllLicenses() map[string]LicenseRecord
AllLicenses returns the full embedded SPDX license database.
func BatchFetchGitHubLicenses ¶
func BatchFetchGitHubLicenses(packages []PackageLicense, onProgress func(resolved, total int))
BatchFetchGitHubLicenses resolves licenses for GitHub-hosted packages concurrently. Handles github.com/ prefixed packages (Go), owner/repo packages (GHA, Terraform), and any other package that maps to a GitHub repository.
func BatchFetchLicenses ¶
func BatchFetchLicenses(packages []PackageLicense, onProgress func(resolved, total int))
BatchFetchLicenses resolves licenses for multiple packages concurrently via deps.dev. It modifies the slice in place, setting LicenseSpdxID and LicenseSource for resolved packages.
func BatchFetchRegistryLicenses ¶
func BatchFetchRegistryLicenses(packages []PackageLicense, onProgress func(resolved, total int))
BatchFetchRegistryLicenses resolves licenses for packages whose ecosystems have native registry APIs not covered by deps.dev. Modifies slice in place, setting LicenseSpdxID and LicenseSource = "registry" for resolved packages.
func BuildSARIFFromAnalysis ¶ added in v3.7.0
func BuildSARIFFromAnalysis(result *AnalysisResult) ([]SARIFFinding, []SARIFRule)
BuildSARIFFromAnalysis converts the analysis result into SARIFFinding + SARIFRule slices. Each LicenseConflict becomes a finding with a rule id like "license-conflict-incompatible". Findings ([]license.Finding) become rules like "license-policy-{category}" carrying the package PURL and severity.
func CanonicalSPDXID ¶ added in v3.41.0
CanonicalSPDXID returns the canonical SPDX identifier for a case-insensitive input when it is a recognised single SPDX license, or "" otherwise.
Unlike NormalizeSPDX (which echoes unknown input back), this reports recognisability, so CycloneDX writers can decide whether a value is safe to emit as the schema-constrained license.id versus a free-form license.name. The embedded SPDX database is a subset of the SPDX enum baked into the CycloneDX schema, so a non-empty result is always accepted as license.id.
func ClassifyLicenseText ¶
ClassifyLicenseText identifies a license SPDX ID from the full text content. Uses keyword matching — not a full license parser, but handles the vast majority of standard open-source licenses.
func ConflictFindingID ¶ added in v3.57.0
func ConflictFindingID(c LicenseConflict) string
ConflictFindingID builds the stable identifier for a license-conflict finding. The license and package pairs are each sorted so that the same conflict discovered from either direction yields one identifier.
func CountFindingsAtOrAbove ¶
CountFindingsAtOrAbove counts findings at or above the given severity threshold.
func FetchContainerLicense ¶
FetchContainerLicense attempts to resolve a license for a container image or infrastructure-as-code package. Tries local tools first, then registry APIs.
Handles:
- Docker/OCI images (podman/docker inspect → labels/annotations → registry)
- Terraform providers (registry API → GitHub source repo)
- Nix flakes (nix CLI if available)
func FetchFromEcosystemRegistry ¶
func FetchFromEcosystemRegistry(pkg PackageLicense) string
FetchFromEcosystemRegistry attempts to resolve a license from the package's native ecosystem registry for ecosystems not covered by deps.dev.
func FetchLicenseFromDepsDev ¶
FetchLicenseFromDepsDev queries api.deps.dev for a package's license. Returns the SPDX license ID or "" if not found/unsupported.
func FetchLicenseFromGitHub ¶
FetchLicenseFromGitHub resolves a license for a GitHub-hosted package. Uses a multi-strategy approach:
- GitHub repo API .license.spdx_id field (via gh CLI or REST API)
- Dedicated /repos/{owner}/{repo}/license endpoint
- Fetch LICENSE/COPYING file content and classify text
- Discover license files via directory listing
func FindLicenseInDir ¶
FindLicenseInDir searches for a license file in the given directory and classifies it. Works for any ecosystem where deps are on the filesystem.
func FindLicenseInModuleCache ¶
FindLicenseInModuleCache looks for a license file in the Go module cache for the given module and version, reads it, and classifies the license. Returns "" if not found or unclassifiable.
func FindingID ¶ added in v3.57.0
func FindingID(category string, pkg PackageLicense) string
FindingID builds the stable identifier for a per-package license finding.
Identifiers must survive across runs: memory reconciliation resolves a finding by noticing its ID has disappeared from the current result set, and the SARIF partialFingerprint is derived from it. A run-local counter would make both meaningless, since the ordinal depends on package iteration order.
The SPDX id is deliberately absent: a package resolves to exactly one license per run, so <category>:<ecosystem>:<package>@<version> is already unique, and omitting it lets legacy counter-keyed memory records be migrated (a FindingRecord stores no license field).
func FindingsToCDXVulnerabilities ¶
func FindingsToCDXVulnerabilities(findings []Finding, packages []PackageLicense) []cdx.Vulnerability
FindingsToCDXVulnerabilities converts license findings to CycloneDX vulnerability entries.
func MarshalSPDXJSON ¶
func MarshalSPDXJSON(doc *SPDXDocument) ([]byte, error)
MarshalSPDXJSON serialises an SPDX document to indented JSON.
func MergeBOM ¶
func MergeBOM(existingPath string, newVulns []cdx.Vulnerability, source string) error
MergeBOM reads an existing BOM from path, replaces all vulnerabilities with the given source name, appends the new vulnerabilities, and writes back. If the file doesn't exist, it creates a minimal BOM with just the new vulnerabilities.
func NormalizeSPDX ¶
NormalizeSPDX returns the canonical SPDX ID for a case-insensitive input, or the input unchanged if not found in the database.
func ParseSPDXExpression ¶
ParseSPDXExpression splits a simple SPDX license expression into constituent IDs. Handles "MIT", "MIT OR Apache-2.0", "GPL-2.0-only WITH Classpath-exception-2.0", and parenthesised groups. WITH exceptions are stripped.
func PopulateBOMLicenses ¶
func PopulateBOMLicenses(bomPath string, packages []PackageLicense, groups []scan.ManifestGroup)
PopulateBOMLicenses reads an existing BOM, populates component licenses and the dependency tree, then writes it back. This is used by the standalone license command to enrich an existing BOM without rebuilding it. If the BOM has no components, they are created from the package list.
Types ¶
type AllowList ¶
type AllowList struct {
Licenses []string `yaml:"licenses"`
}
AllowList is a set of approved SPDX license IDs.
func LoadAllowListFromFile ¶
LoadAllowListFromFile reads a YAML allow list file. Expected format:
licenses: - MIT - Apache-2.0
func ParseAllowListCSV ¶
ParseAllowListCSV parses a comma-separated list of SPDX IDs.
type AnalysisResult ¶
type AnalysisResult struct {
Mode string `json:"mode"`
Packages []PackageLicense `json:"packages"`
Conflicts []LicenseConflict `json:"conflicts"`
Findings []Finding `json:"findings"`
Summary AnalysisSummary `json:"summary"`
}
AnalysisResult is the complete output of a license analysis run.
func Evaluate ¶
func Evaluate(packages []PackageLicense, cfg EvalConfig) *AnalysisResult
Evaluate runs all license evaluation rules against the detected packages.
type AnalysisSummary ¶
type AnalysisSummary struct {
TotalPackages int `json:"totalPackages"`
LicenseCounts map[string]int `json:"licenseCounts"`
CategoryCounts map[Category]int `json:"categoryCounts"`
ConflictCount int `json:"conflictCount"`
FindingsBySev map[string]int `json:"findingsBySeverity"`
OsiApproved int `json:"osiApproved"`
FsfLibre int `json:"fsfLibre"`
Deprecated int `json:"deprecated"`
Unknown int `json:"unknown"`
// Exempted is the count an approved exception covers, and Effective is what
// remains. The same split VEX uses for vulnerabilities, for the same
// reason: the number to act on is not the number found.
Exempted int `json:"exempted"`
Effective int `json:"effective"`
// ExpiredExceptions counts findings whose exception has lapsed. They are
// live findings; the count exists so a lapse is visible rather than
// arriving as an unexplained new violation.
ExpiredExceptions int `json:"expiredExceptions"`
}
AnalysisSummary provides aggregate counts.
type Applied ¶ added in v3.97.0
type Applied struct {
// Exception is the governance metadata.
Exception Exception
// Kind is "blanket" or "package".
Kind string
// Match describes what the exception was written against.
Match string
// Expired reports that the exception has lapsed and did NOT apply.
Expired bool
}
Applied is a matched exception, with why it matched.
type BlanketException ¶ added in v3.97.0
type BlanketException struct {
// License is the SPDX id. Matching is by prefix, so an exception for
// MPL-2.0 also covers MPL-2.0-no-copyleft-exception: they are the same
// licence with a variation nobody writes a separate exception for.
License string `yaml:"license" json:"license"`
Exception `yaml:",inline" json:",inline"`
}
BlanketException exempts a licence wherever it is found.
type Category ¶
type Category string
Category classifies a license by its copyleft characteristics.
func ClassifyCategory ¶
ClassifyCategory returns the license category for a given SPDX ID.
type ConflictSeverity ¶
ConflictSeverity describes a conflict rule result.
func CategoryConflict ¶
func CategoryConflict(cat1, cat2 Category) *ConflictSeverity
CategoryConflict checks if two license categories conflict and returns severity info. Returns nil if the combination is compatible.
func IDConflict ¶
func IDConflict(id1, id2 string) *ConflictSeverity
IDConflict checks for specific SPDX ID pair overrides. Returns nil if no specific rule exists.
type EvalConfig ¶
type EvalConfig struct {
Mode string // "inclusive" or "individual"
AllowedLicenses []string // SPDX IDs; empty = no allow list
SeverityThreshold string // "critical", "high", "medium", "low"
// Policy is the declarative licence policy. Nil falls back to
// DefaultPolicy(), which reproduces the severities the evaluator used
// before policies existed — so adopting one is a deliberate change rather
// than something that arrives with an upgrade and turns a build red.
Policy *Policy
// Exceptions is the approved-exception set. Nil means no exceptions.
Exceptions *ExceptionSet
// Project selects per-project policy overrides, from --project.
Project string
// Now is the clock used for exception expiry. Zero means time.Now().
Now time.Time
}
EvalConfig controls evaluation behaviour.
type EvidenceStep ¶
type EvidenceStep struct {
Rule string `json:"rule"`
Input string `json:"input"`
Expected string `json:"expected,omitempty"`
Actual string `json:"actual,omitempty"`
Result string `json:"result"` // "PASS" or "FAIL"
}
EvidenceStep is one step in a rule evaluation trace.
type Exception ¶ added in v3.97.0
type Exception struct {
// ID is a stable identifier for referring to this exception in a report.
ID string `yaml:"id,omitempty" json:"id,omitempty"`
// Reason is why the exception exists. Required: an exception nobody can
// explain is indistinguishable from a mistake.
Reason string `yaml:"reason" json:"reason"`
// Scope narrows the claim, e.g. "vendored, unmodified, dynamically linked".
Scope string `yaml:"scope,omitempty" json:"scope,omitempty"`
// Approver is who signed it off.
Approver string `yaml:"approver,omitempty" json:"approver,omitempty"`
// ApprovedDate is when, as YYYY-MM-DD.
ApprovedDate string `yaml:"approvedDate,omitempty" json:"approvedDate,omitempty"`
// Expires is when the exception lapses, as YYYY-MM-DD. Empty never expires.
Expires string `yaml:"expires,omitempty" json:"expires,omitempty"`
// Projects limits the exception to named projects. Empty applies everywhere.
Projects []string `yaml:"projects,omitempty" json:"projects,omitempty"`
}
Exception is the governance metadata every exception carries.
func (Exception) AppliesToProject ¶ added in v3.97.0
AppliesToProject reports whether the exception covers a project.
func (Exception) Expired ¶ added in v3.97.0
Expired reports whether the exception has lapsed as of now.
An expired exception is not a soft signal: the finding reverts to a violation. That is the whole reason an expiry is worth writing down — an exception that quietly outlives its review is the failure mode this is designed to prevent.
type ExceptionSet ¶ added in v3.97.0
type ExceptionSet struct {
APIVersion string `yaml:"apiVersion" json:"apiVersion"`
Kind string `yaml:"kind" json:"kind"`
// Blanket exempts a licence everywhere it appears.
Blanket []BlanketException `yaml:"blanket,omitempty" json:"blanket,omitempty"`
// Packages exempts a specific package, optionally under a specific licence.
Packages []PackageException `yaml:"packages,omitempty" json:"packages,omitempty"`
}
ExceptionSet is a collection of licence exceptions.
func LoadExceptions ¶ added in v3.97.0
func LoadExceptions(path string) (*ExceptionSet, error)
LoadExceptions reads an exception set from a YAML file.
func ParseExceptions ¶ added in v3.97.0
func ParseExceptions(data []byte) (*ExceptionSet, error)
ParseExceptions parses an exception document.
func (*ExceptionSet) Expiring ¶ added in v3.97.0
Expiring returns exceptions lapsing within the given window, soonest first.
An exception that expires without anyone noticing turns into a surprise red build. Being able to ask "what lapses in the next 30 days" is what makes the expiry a review cadence rather than a trap.
func (*ExceptionSet) MarshalYAML ¶ added in v3.97.0
func (s *ExceptionSet) MarshalYAML() ([]byte, error)
MarshalYAML renders the exception set as a YAML document.
func (*ExceptionSet) Match ¶ added in v3.97.0
func (s *ExceptionSet) Match(pkg PackageLicense, project string, now time.Time) (Applied, bool)
Match finds the exception covering a package, if any.
Returns the applied exception and whether it exempts the finding. An expired exception is returned with Expired set and exempts nothing: the caller reports why the finding is live rather than leaving the user to wonder why their exception stopped working.
func (*ExceptionSet) Validate ¶ added in v3.97.0
func (s *ExceptionSet) Validate() error
Validate checks an exception document for structural problems.
type Finding ¶
type Finding struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Severity string `json:"severity"`
Confidence float64 `json:"confidence"`
Package PackageLicense `json:"package"`
Category string `json:"category"` // rule category
Evidence []EvidenceStep `json:"evidence"`
IntroducedPaths [][]string `json:"introducedPaths,omitempty"`
PathCount int `json:"pathCount,omitempty"`
// Exempted marks a finding an approved exception covers. Exempted findings
// are retained and badged, never dropped: a violation count that fell
// because somebody wrote an exception is a different fact from one that
// fell because the dependency was removed, and a report that cannot tell
// them apart is not an audit trail.
Exempted bool `json:"exempted,omitempty"`
// ExemptionReason is why the exception exists.
ExemptionReason string `json:"exemptionReason,omitempty"`
// ExemptionLabel attributes the exception — its id, approver and expiry.
ExemptionLabel string `json:"exemptionLabel,omitempty"`
// ExemptionExpired marks a finding whose exception has lapsed. It is NOT
// exempted; the field exists so the report can say why an exception the
// user wrote is no longer working.
ExemptionExpired bool `json:"exemptionExpired,omitempty"`
}
Finding is a single license issue produced by evaluation.
type LicenseConflict ¶
type LicenseConflict struct {
Type string `json:"type"` // "incompatible", "copyleft-mixing", "deprecated", "version-incompatible"
Severity string `json:"severity"` // critical, high, medium, low
License1 string `json:"license1"`
License2 string `json:"license2"`
Package1 string `json:"package1"`
Package2 string `json:"package2"`
Description string `json:"description"`
Recommendation string `json:"recommendation"`
Package1Paths [][]string `json:"package1Paths,omitempty"`
Package2Paths [][]string `json:"package2Paths,omitempty"`
}
LicenseConflict describes an incompatibility between two licenses.
type LicenseRecord ¶
type LicenseRecord struct {
SpdxID string `json:"spdxId" yaml:"spdx_id"`
Name string `json:"name" yaml:"name"`
Category Category `json:"category" yaml:"category"`
IsOsiApproved bool `json:"isOsiApproved" yaml:"osi_approved"`
IsFsfLibre bool `json:"isFsfLibre" yaml:"fsf_libre"`
IsDeprecated bool `json:"isDeprecated" yaml:"deprecated"`
}
LicenseRecord describes a single SPDX license entry.
func LookupSPDX ¶
func LookupSPDX(id string) *LicenseRecord
LookupSPDX returns the license record for the given SPDX ID, or nil if not found. Lookup is case-insensitive.
type PackageException ¶ added in v3.97.0
type PackageException struct {
// Purl matches the package, with '*' as a wildcard segment. A glob is the
// useful form: an organisation vendoring every hashicorp module writes
// pkg:golang/github.com/hashicorp/* once rather than an entry per module.
Purl string `yaml:"purl,omitempty" json:"purl,omitempty"`
// Name matches the package name as a substring, for ecosystems where the
// short name and the fully-qualified module path are both in use.
Name string `yaml:"name,omitempty" json:"name,omitempty"`
// License narrows the exception to one licence. Empty exempts the package
// whatever licence it turns out to carry, which is a broader claim and
// should be rarer.
License string `yaml:"license,omitempty" json:"license,omitempty"`
Exception `yaml:",inline" json:",inline"`
}
PackageException exempts one package.
type PackageLicense ¶
type PackageLicense struct {
PackageName string `json:"packageName"`
PackageVersion string `json:"packageVersion"`
Ecosystem string `json:"ecosystem"`
Scope string `json:"scope"`
LicenseSpdxID string `json:"licenseSpdxId"`
LicenseSource string `json:"licenseSource"` // "manifest", "lockfile", "embedded-db"
SourceFile string `json:"sourceFile"`
IsDirect bool `json:"isDirect"`
GitHubURL string `json:"-"` // optional: "owner/repo" from manifest, used for license resolution
Record *LicenseRecord `json:"record,omitempty"`
IntroducedPaths [][]string `json:"introducedPaths,omitempty"`
PathCount int `json:"pathCount,omitempty"`
}
PackageLicense ties a detected package to its resolved license.
func DetectLicenses ¶
func DetectLicenses(packages []scan.ScopedPackage, groups []scan.ManifestGroup) []PackageLicense
DetectLicenses takes already-parsed packages and resolves their licenses. It reads the original manifest files to extract license fields where possible, falling back to the embedded SPDX database for well-known packages. When groups is non-nil, dependency paths are computed for each package.
type Policy ¶ added in v3.97.0
type Policy struct {
APIVersion string `yaml:"apiVersion" json:"apiVersion"`
Kind string `yaml:"kind" json:"kind"`
// Categories reassigns SPDX ids to categories, overriding the embedded
// classification. An organisation's counsel may classify a licence
// differently from the default, and that decision belongs in their policy
// rather than in a fork of this CLI.
Categories map[Category][]string `yaml:"categories,omitempty" json:"categories,omitempty"`
// Severity maps a category to the severity of a finding against it.
Severity map[Category]string `yaml:"severity,omitempty" json:"severity,omitempty"`
// Unknown says what to do about an unresolved licence.
Unknown UnknownHandling `yaml:"unknown,omitempty" json:"unknown,omitempty"`
// Scopes says how each dependency scope is treated.
Scopes map[string]ScopeHandling `yaml:"scopes,omitempty" json:"scopes,omitempty"`
// Projects holds per-project overrides, keyed on the --project label. A
// monorepo's payment service and its docs site have different obligations,
// and forcing them to share one threshold means the stricter one wins
// everywhere or the looser one wins everywhere.
Projects map[string]ProjectPolicy `yaml:"projects,omitempty" json:"projects,omitempty"`
// contains filtered or unexported fields
}
Policy is a declarative licence policy.
func DefaultPolicy ¶ added in v3.97.0
func DefaultPolicy() *Policy
DefaultPolicy is the policy applied when none is supplied.
It reproduces exactly what the evaluator did before policies existed, so adopting a policy file is a change a team makes deliberately rather than one that arrives with an upgrade and turns their build red. Two consequences are deliberate and easy to get wrong:
- Only strong copyleft carries a severity. Proprietary arguably should too, but it did not before, and quietly adding it would fail builds on an upgrade for a decision nobody made.
- No scope is ignored. Scope filtering is genuinely useful — a copyleft build tool that never ships is not a licence obligation — but turning it on by default would silently stop reporting findings that were being reported yesterday, which is the more dangerous direction to be wrong in.
A policy file opts into both. RecommendedPolicy() is the starting point.
func LoadPolicy ¶ added in v3.97.0
LoadPolicy reads a policy from a YAML file.
func ParsePolicy ¶ added in v3.97.0
ParsePolicy parses a policy document, filling defaults for absent fields.
func RecommendedPolicy ¶ added in v3.97.0
func RecommendedPolicy() *Policy
RecommendedPolicy is the starting point `license policy init` writes.
Unlike DefaultPolicy it makes the judgements a team adopting a policy generally wants: proprietary licences are a finding, network copyleft is critical because the obligation triggers on use rather than distribution, and dependencies that are never shipped are out of scope.
func (*Policy) CategoryFor ¶ added in v3.97.0
CategoryFor returns the category for an SPDX id under this policy.
A policy override wins over the embedded classification, which is the point: the embedded database is a reasonable default, not an authority on what a particular organisation has decided about a particular licence.
func (*Policy) EvaluatesScope ¶ added in v3.97.0
EvaluatesScope reports whether a dependency scope is in scope for the policy.
func (*Policy) MarshalYAML ¶ added in v3.97.0
MarshalYAML renders the policy as a YAML document.
func (*Policy) SeverityFor ¶ added in v3.97.0
SeverityFor returns the severity a category carries, honouring per-project overrides. An empty result means the category produces no finding.
func (*Policy) UnknownFor ¶ added in v3.97.0
func (p *Policy) UnknownFor(project string) UnknownHandling
UnknownFor returns the unknown-licence handling, honouring project overrides.
type ProjectPolicy ¶ added in v3.97.0
type ProjectPolicy struct {
Severity map[Category]string `yaml:"severity,omitempty" json:"severity,omitempty"`
Unknown UnknownHandling `yaml:"unknown,omitempty" json:"unknown,omitempty"`
Scopes map[string]ScopeHandling `yaml:"scopes,omitempty" json:"scopes,omitempty"`
}
ProjectPolicy overrides parts of the policy for one project.
type RepoLicenseHit ¶ added in v3.7.0
type RepoLicenseHit struct {
SPDXID string `json:"spdxId,omitempty"`
Name string `json:"name,omitempty"`
URL string `json:"url,omitempty"`
Source string `json:"source,omitempty"` // "file:LICENSE" | "manifest:package.json"
Acknowledge string `json:"acknowledgement,omitempty"` // "declared" | "concluded"
Text string `json:"text,omitempty"` // first N bytes of license text
}
RepoLicenseHit mirrors the shape vdb-api expects on CliEnv.Licenses.
func DetectRepoLicense ¶ added in v3.7.0
func DetectRepoLicense(repoRoot string) []RepoLicenseHit
DetectRepoLicense scans the given repo root for license signals. Returns one hit per distinct (SPDX, source) tuple. Always returns nil rather than an error on read failure — license detection is best-effort context.
type SARIFFinding ¶ added in v3.7.0
type SARIFFinding struct {
RuleID string
RuleName string
Message string
Severity string
Level string
ArtifactURI string
PackagePurl string
Fingerprint string
Tags []string
}
SARIFFinding mirrors sast.Finding (kept local so this package does not depend on internal/sast). The cmd layer converts these into the typed vdb.CliSARIFFinding shape before posting.
type SPDXChecksum ¶ added in v3.97.0
type SPDXChecksum struct {
Algorithm string `json:"algorithm"`
ChecksumValue string `json:"checksumValue"`
}
SPDXChecksum is a package checksum entry.
type SPDXCreationInfo ¶
type SPDXCreationInfo struct {
Created string `json:"created"`
Creators []string `json:"creators"`
LicenseListVersion string `json:"licenseListVersion,omitempty"`
Comment string `json:"comment,omitempty"`
}
SPDXCreationInfo describes when and by whom the SPDX document was created.
type SPDXDocument ¶
type SPDXDocument struct {
SPDXVersion string `json:"spdxVersion"`
DataLicense string `json:"dataLicense"`
SPDXID string `json:"SPDXID"`
Name string `json:"name"`
DocumentNamespace string `json:"documentNamespace"`
CreationInfo SPDXCreationInfo `json:"creationInfo"`
Packages []SPDXPackage `json:"packages"`
Relationships []SPDXRelationship `json:"relationships,omitempty"`
ExtractedLicensingInfos []SPDXExtractedLicense `json:"extractedLicensingInfos,omitempty"`
DocumentDescribes []string `json:"documentDescribes,omitempty"`
Comment string `json:"comment,omitempty"`
}
SPDXDocument represents an SPDX 2.x JSON document.
The fields BuildSPDXDocument writes are the required core; the rest carry `omitempty` and exist for the read side, so a document this package builds serialises exactly as it did before they were added. internal/bom parses third-party SPDX (Syft, BuildKit, cdxgen) through this same struct set — dropping supplier and checksum data on the way in would leave the SBOM quality check unable to see fields that are demonstrably present.
func BuildSPDXDocument ¶
func BuildSPDXDocument(result *AnalysisResult, name string) *SPDXDocument
BuildSPDXDocument creates an SPDX 2.3 JSON document from license analysis results.
type SPDXExternalRef ¶
type SPDXExternalRef struct {
ReferenceCategory string `json:"referenceCategory"`
ReferenceType string `json:"referenceType"`
ReferenceLocator string `json:"referenceLocator"`
}
SPDXExternalRef is a package external reference.
type SPDXExtractedLicense ¶
type SPDXExtractedLicense struct {
LicenseID string `json:"licenseId"`
ExtractedText string `json:"extractedText"`
Name string `json:"name"`
}
SPDXExtractedLicense captures non-standard license text.
type SPDXPackage ¶
type SPDXPackage struct {
SPDXID string `json:"SPDXID"`
Name string `json:"name"`
VersionInfo string `json:"versionInfo,omitempty"`
DownloadLocation string `json:"downloadLocation"`
LicenseConcluded string `json:"licenseConcluded"`
LicenseDeclared string `json:"licenseDeclared"`
CopyrightText string `json:"copyrightText"`
FilesAnalyzed bool `json:"filesAnalyzed"`
ExternalRefs []SPDXExternalRef `json:"externalRefs,omitempty"`
// Read-side fields — see the SPDXDocument doc comment.
Supplier string `json:"supplier,omitempty"`
Originator string `json:"originator,omitempty"`
Homepage string `json:"homepage,omitempty"`
Description string `json:"description,omitempty"`
Summary string `json:"summary,omitempty"`
SourceInfo string `json:"sourceInfo,omitempty"`
PackageFileName string `json:"packageFileName,omitempty"`
PrimaryPackagePurpose string `json:"primaryPackagePurpose,omitempty"`
Checksums []SPDXChecksum `json:"checksums,omitempty"`
}
SPDXPackage is an SPDX package entry.
type SPDXRelationship ¶
type SPDXRelationship struct {
Element string `json:"spdxElementId"`
RelType string `json:"relationshipType"`
RelatedElement string `json:"relatedSpdxElement"`
Comment string `json:"comment,omitempty"`
}
SPDXRelationship defines a relationship between SPDX elements.
type ScopeHandling ¶ added in v3.97.0
type ScopeHandling string
ScopeHandling says how a dependency scope is treated.
const ( // ScopeEvaluate applies the policy to this scope. ScopeEvaluate ScopeHandling = "evaluate" // ScopeIgnore skips it. Development and test dependencies are not // distributed, so a copyleft build tool is usually not a licence obligation. ScopeIgnore ScopeHandling = "ignore" )
type UnknownHandling ¶ added in v3.97.0
type UnknownHandling string
UnknownHandling says what to do about a licence that could not be resolved.
const ( // UnknownWarn reports unresolved licences without failing. The default: an // unresolved licence is a gap in the data, not evidence of a violation, and // failing on it would make the policy unusable on any real dependency tree. UnknownWarn UnknownHandling = "warn" // UnknownFail treats an unresolved licence as a violation. For teams whose // compliance position is that an unidentified licence cannot be shipped. UnknownFail UnknownHandling = "fail" // UnknownIgnore drops unresolved licences entirely. UnknownIgnore UnknownHandling = "ignore" )