component

package
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2026 License: GPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package component provides the component domain model for software dependencies.

Index

Constants

View Source
const (
	// MaxMetadataSize is the maximum allowed size for component metadata (64KB)
	MaxMetadataSize = 64 * 1024
	// MaxMetadataKeys is the maximum number of keys in metadata
	MaxMetadataKeys = 100
)

Security limits

Variables

View Source
var (
	ErrComponentNotFound      = fmt.Errorf("component %w", shared.ErrNotFound)
	ErrComponentAlreadyExists = fmt.Errorf("component %w", shared.ErrAlreadyExists)
	ErrDependencyNotFound     = fmt.Errorf("dependency %w", shared.ErrNotFound)
)

Domain errors for component.

Functions

func AlreadyExistsError

func AlreadyExistsError(purl string) error

AlreadyExistsError returns an already exists error with the component PURL.

func BuildPURL

func BuildPURL(ecosystem Ecosystem, namespace, name, version string) string

BuildPURL builds a Package URL (PURL) for a component. Format: pkg:ecosystem/namespace/name@version

func NotFoundByPURLError

func NotFoundByPURLError(purl string) error

NotFoundByPURLError returns a not found error with the component PURL.

func NotFoundError

func NotFoundError(id shared.ID) error

NotFoundError returns a not found error with the component ID.

Types

type AssetDependency

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

AssetDependency represents a component usage by an asset.

func NewAssetDependency

func NewAssetDependency(
	tenantID, assetID, componentID shared.ID,
	path string,
	depType DependencyType,
) (*AssetDependency, error)

NewAssetDependency creates a link between asset and component. Default depth is 1 (direct dependency). Use SetDepth() for transitive deps.

func ReconstituteAssetDependency

func ReconstituteAssetDependency(
	id, tenantID, assetID, componentID shared.ID,
	path string,
	depType DependencyType,
	manifestFile string,
	parentComponentID *shared.ID,
	depth int,
	createdAt, updatedAt time.Time,
) *AssetDependency

ReconstituteAssetDependency recreates a dependency link.

func (*AssetDependency) AssetID

func (ad *AssetDependency) AssetID() shared.ID

func (*AssetDependency) Component

func (ad *AssetDependency) Component() *Component

func (*AssetDependency) ComponentID

func (ad *AssetDependency) ComponentID() shared.ID

func (*AssetDependency) CreatedAt

func (ad *AssetDependency) CreatedAt() time.Time

func (*AssetDependency) DependencyType

func (ad *AssetDependency) DependencyType() DependencyType

func (*AssetDependency) Depth

func (ad *AssetDependency) Depth() int

func (*AssetDependency) ID

func (ad *AssetDependency) ID() shared.ID

func (*AssetDependency) ManifestFile

func (ad *AssetDependency) ManifestFile() string

func (*AssetDependency) ParentComponentID

func (ad *AssetDependency) ParentComponentID() *shared.ID

func (*AssetDependency) Path

func (ad *AssetDependency) Path() string

func (*AssetDependency) SetComponent

func (ad *AssetDependency) SetComponent(c *Component)

func (*AssetDependency) SetDependencyType added in v0.1.2

func (ad *AssetDependency) SetDependencyType(t DependencyType)

SetDependencyType updates the dependency type.

func (*AssetDependency) SetDepth

func (ad *AssetDependency) SetDepth(depth int)

SetDepth sets the dependency depth for risk scoring.

func (*AssetDependency) SetManifestFile added in v0.1.2

func (ad *AssetDependency) SetManifestFile(f string)

SetManifestFile updates the manifest file.

func (*AssetDependency) SetParentComponentID

func (ad *AssetDependency) SetParentComponentID(parentID *shared.ID) error

SetParentComponentID sets the parent dependency ID for transitive deps. Returns error if attempting to create a circular dependency (self-reference).

func (*AssetDependency) SetPath added in v0.1.2

func (ad *AssetDependency) SetPath(p string)

SetPath updates the dependency path.

func (*AssetDependency) TenantID

func (ad *AssetDependency) TenantID() shared.ID

func (*AssetDependency) UpdatedAt

func (ad *AssetDependency) UpdatedAt() time.Time

type Component

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

Component represents a unique software package (Global).

func NewComponent

func NewComponent(
	name string,
	version string,
	ecosystem Ecosystem,
) (*Component, error)

NewComponent creates a new Global Component.

func Reconstitute

func Reconstitute(
	id shared.ID,
	name string,
	version string,
	ecosystem Ecosystem,
	purl string,
	license string,
	description string,
	homepage string,
	vulnerabilityCount int,
	metadata map[string]any,
	createdAt time.Time,
	updatedAt time.Time,
) *Component

Reconstitute recreates a Component from persistence.

func (*Component) CreatedAt

func (c *Component) CreatedAt() time.Time

CreatedAt returns the creation time.

func (*Component) Description

func (c *Component) Description() string

Description returns the description.

func (*Component) Ecosystem

func (c *Component) Ecosystem() Ecosystem

Ecosystem returns the ecosystem.

func (*Component) Homepage

func (c *Component) Homepage() string

Homepage returns the homepage.

func (*Component) ID

func (c *Component) ID() shared.ID

ID returns the component ID.

func (*Component) License

func (c *Component) License() string

License returns the license.

func (*Component) Metadata

func (c *Component) Metadata() map[string]any

Metadata returns a copy of the metadata.

func (*Component) Name

func (c *Component) Name() string

Name returns the component name.

func (*Component) PURL

func (c *Component) PURL() string

PURL returns the Package URL.

func (*Component) SetMetadata

func (c *Component) SetMetadata(key string, value any) error

SetMetadata sets a metadata key-value pair with size validation. Returns error if metadata exceeds size limits (DoS prevention).

func (*Component) SetPURL

func (c *Component) SetPURL(purl string)

SetPURL overrides the generated PURL with a custom one. Use this when the agent provides a more accurate PURL.

func (*Component) UpdateDescription

func (c *Component) UpdateDescription(desc string)

func (*Component) UpdateHomepage

func (c *Component) UpdateHomepage(url string)

func (*Component) UpdateLicense

func (c *Component) UpdateLicense(license string)

func (*Component) UpdatedAt

func (c *Component) UpdatedAt() time.Time

UpdatedAt returns the last update time.

func (*Component) Version

func (c *Component) Version() string

Version returns the version.

func (*Component) VulnerabilityCount

func (c *Component) VulnerabilityCount() int

VulnerabilityCount returns the vulnerability count.

type ComponentStats

type ComponentStats struct {
	TotalComponents        int `json:"total_components"`
	DirectDependencies     int `json:"direct_dependencies"`
	TransitiveDependencies int `json:"transitive_dependencies"`
	VulnerableComponents   int `json:"vulnerable_components"`

	// Extended stats from findings analysis
	TotalVulnerabilities int            `json:"total_vulnerabilities"`
	OutdatedComponents   int            `json:"outdated_components"`
	CisaKevComponents    int            `json:"cisa_kev_components"`
	VulnBySeverity       map[string]int `json:"vuln_by_severity"` // critical, high, medium, low
	LicenseRisks         map[string]int `json:"license_risks"`    // critical, high, medium, low
}

ComponentStats aggregates counts for dashboard.

type DependencyType

type DependencyType string

DependencyType represents whether a dependency is direct or transitive.

const (
	DependencyTypeDirect     DependencyType = "direct"
	DependencyTypeTransitive DependencyType = "transitive"
	DependencyTypeDev        DependencyType = "dev"
	DependencyTypeOptional   DependencyType = "optional"
)

func ParseDependencyType

func ParseDependencyType(s string) (DependencyType, error)

ParseDependencyType parses a string into a DependencyType. Handles mapping from various scanner formats (e.g., Trivy uses "indirect", "transit").

func (DependencyType) IsValid

func (d DependencyType) IsValid() bool

IsValid checks if the dependency type is valid.

func (DependencyType) String

func (d DependencyType) String() string

String returns the string representation.

type Ecosystem

type Ecosystem string

Ecosystem represents the package ecosystem.

const (
	EcosystemNPM       Ecosystem = "npm"
	EcosystemMaven     Ecosystem = "maven"
	EcosystemPyPI      Ecosystem = "pypi"
	EcosystemGo        Ecosystem = "go"
	EcosystemCargo     Ecosystem = "cargo"
	EcosystemNuGet     Ecosystem = "nuget"
	EcosystemRubyGems  Ecosystem = "rubygems"
	EcosystemComposer  Ecosystem = "composer"
	EcosystemHex       Ecosystem = "hex"
	EcosystemCocoaPods Ecosystem = "cocoapods"
	EcosystemSwiftPM   Ecosystem = "swiftpm"
	EcosystemPub       Ecosystem = "pub"
	EcosystemCran      Ecosystem = "cran"
	EcosystemOther     Ecosystem = "other"
)

func AllEcosystems

func AllEcosystems() []Ecosystem

AllEcosystems returns all valid ecosystems.

func ParseEcosystem

func ParseEcosystem(s string) (Ecosystem, error)

ParseEcosystem parses a string into an Ecosystem.

func (Ecosystem) IsValid

func (e Ecosystem) IsValid() bool

IsValid checks if the ecosystem is valid.

func (Ecosystem) ManifestFile

func (e Ecosystem) ManifestFile() string

ManifestFile returns the typical manifest file for this ecosystem.

func (Ecosystem) String

func (e Ecosystem) String() string

String returns the string representation.

type EcosystemStats

type EcosystemStats struct {
	Ecosystem    string `json:"ecosystem"`
	Total        int    `json:"total"`
	Vulnerable   int    `json:"vulnerable"`
	Outdated     int    `json:"outdated"`
	ManifestFile string `json:"manifest_file"`
}

EcosystemStats represents statistics for a single ecosystem.

type Filter

type Filter struct {
	TenantID           *shared.ID // Filter components used by tenant
	AssetID            *shared.ID // Filter components used by asset
	Name               *string
	PURL               *string
	Ecosystems         []Ecosystem
	DependencyTypes    []DependencyType
	Statuses           []Status
	Licenses           []string
	HasVulnerabilities *bool
}

Filter defines criteria for filtering components.

func NewFilter

func NewFilter() Filter

NewFilter creates a new empty filter.

func (Filter) WithAssetID

func (f Filter) WithAssetID(id shared.ID) Filter

func (Filter) WithDependencyTypes

func (f Filter) WithDependencyTypes(types ...DependencyType) Filter

func (Filter) WithEcosystems

func (f Filter) WithEcosystems(ecosystems ...Ecosystem) Filter

func (Filter) WithHasVulnerabilities

func (f Filter) WithHasVulnerabilities(has bool) Filter

func (Filter) WithLicenses

func (f Filter) WithLicenses(licenses ...string) Filter

func (Filter) WithName

func (f Filter) WithName(name string) Filter

func (Filter) WithStatuses

func (f Filter) WithStatuses(statuses ...Status) Filter

func (Filter) WithTenantID

func (f Filter) WithTenantID(id shared.ID) Filter

type LicenseStats

type LicenseStats struct {
	LicenseID string  `json:"license_id"`    // SPDX identifier
	Name      string  `json:"name"`          // Human-readable name
	Category  string  `json:"category"`      // permissive, copyleft, weak-copyleft, proprietary, public-domain, unknown
	Risk      string  `json:"risk"`          // critical, high, medium, low, none, unknown
	URL       *string `json:"url,omitempty"` // Link to license text (SPDX URL)
	Count     int     `json:"count"`         // Number of components using this license
}

LicenseStats represents statistics for a single license.

type Repository

type Repository interface {
	// Global Component Operations
	Upsert(ctx context.Context, comp *Component) (shared.ID, error)
	GetByPURL(ctx context.Context, purl string) (*Component, error)
	GetByID(ctx context.Context, id shared.ID) (*Component, error)

	// License Operations
	// LinkLicenses links licenses to a component and returns the count of newly linked licenses.
	LinkLicenses(ctx context.Context, componentID shared.ID, licenses []string) (linked int, err error)

	// Asset Dependency Operations (Links)
	LinkAsset(ctx context.Context, dep *AssetDependency) error
	GetDependency(ctx context.Context, id shared.ID) (*AssetDependency, error)
	UpdateDependency(ctx context.Context, dep *AssetDependency) error
	DeleteDependency(ctx context.Context, id shared.ID) error
	DeleteByAssetID(ctx context.Context, assetID shared.ID) error

	// GetExistingDependencyByPURL retrieves an existing asset_component by asset and component PURL.
	// Used for parent lookup during rescan when parent component exists from previous scan.
	// Returns nil, nil if not found.
	GetExistingDependencyByPURL(ctx context.Context, assetID shared.ID, purl string) (*AssetDependency, error)

	// GetExistingDependencyByComponentID retrieves an existing asset_component by asset, component, and path.
	// Used for duplicate detection during ingestion.
	// Returns nil, nil if not found.
	GetExistingDependencyByComponentID(ctx context.Context, assetID shared.ID, componentID shared.ID, path string) (*AssetDependency, error)

	// UpdateAssetDependencyParent updates the parent_component_id and depth of an asset_component.
	// Used in three-pass ingestion to set parent references after all components are inserted.
	UpdateAssetDependencyParent(ctx context.Context, id shared.ID, parentID shared.ID, depth int) error

	// ListComponents retrieves global components (optionally filtered by usage).
	ListComponents(ctx context.Context, filter Filter, page pagination.Pagination) (pagination.Result[*Component], error)

	// ListDependencies retrieves dependencies for an asset (joined with component details).
	ListDependencies(ctx context.Context, assetID shared.ID, page pagination.Pagination) (pagination.Result[*AssetDependency], error)

	// GetStats retrieves aggregated component statistics.
	GetStats(ctx context.Context, tenantID shared.ID) (*ComponentStats, error)

	// GetEcosystemStats retrieves per-ecosystem statistics.
	GetEcosystemStats(ctx context.Context, tenantID shared.ID) ([]EcosystemStats, error)

	// GetVulnerableComponents retrieves components with vulnerability details.
	GetVulnerableComponents(ctx context.Context, tenantID shared.ID, limit int) ([]VulnerableComponent, error)

	// GetLicenseStats retrieves license statistics for a tenant.
	GetLicenseStats(ctx context.Context, tenantID shared.ID) ([]LicenseStats, error)
}

Repository defines the interface for component persistence.

type Status

type Status string

Status represents the component status.

const (
	StatusActive     Status = "active"
	StatusDeprecated Status = "deprecated"
	StatusEndOfLife  Status = "end_of_life"
	StatusUnknown    Status = "unknown"
)

func AllStatuses

func AllStatuses() []Status

AllStatuses returns all valid statuses.

func ParseStatus

func ParseStatus(str string) (Status, error)

ParseStatus parses a string into a Status.

func (Status) IsValid

func (s Status) IsValid() bool

IsValid checks if the status is valid.

func (Status) String

func (s Status) String() string

String returns the string representation.

type VulnerableComponent

type VulnerableComponent struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Version   string `json:"version"`
	Ecosystem string `json:"ecosystem"`
	PURL      string `json:"purl"`
	License   string `json:"license,omitempty"`

	// Vulnerability breakdown
	CriticalCount int  `json:"critical_count"`
	HighCount     int  `json:"high_count"`
	MediumCount   int  `json:"medium_count"`
	LowCount      int  `json:"low_count"`
	TotalCount    int  `json:"total_count"`
	InCisaKev     bool `json:"in_cisa_kev"`
}

VulnerableComponent represents a component with vulnerability details for display.

Jump to

Keyboard shortcuts

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