scanoss

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package scanoss is a Go SDK for the SCANOSS component services (cryptography, vulnerabilities, licenses, geoprovenance).

Each decoration is a grouped service on the Client; chunking the request into batches and querying those batches concurrently with a pool of workers is handled internally and is transparent to the caller:

client, err := scanoss.New(scanoss.Config{APIKey: key})
res, err := client.Vulnerabilities.Components(ctx, comps) // batch
res, err := client.Vulnerabilities.Component(ctx, comp)   // single
res, err := client.Licenses.Components(ctx, comps)
res, err := client.Cryptography.Algorithms(ctx, comps)
res, err := client.Geoprovenance.Origins(ctx, comps)

New is the only way to build a Client. Everything client-wide — credentials, endpoint, proxy and TLS, concurrency, retries — is a field of Config, whose zero value is the default configuration.

The client also exposes a batch scan service that uploads WFP fingerprints and returns match results:

res, err := client.Scan.WFP(ctx, wfp) // upload (parallel chunks) + poll

Per-call tuning stays a functional option: WithChunkBytes for the upload block size, WithScanReporter for progress, WithScanIDNotify to capture the scan id for optional recovery via Scan.Wait.

Index

Examples

Constants

View Source
const (
	DefaultAPIURL     = "https://api.scanoss.com"
	DefaultChunkSize  = 10
	DefaultWorkers    = 5
	DefaultMaxRetries = 5
	// DefaultMaxRetryAfter caps a single Retry-After wait.
	DefaultMaxRetryAfter = 5 * time.Minute
	// DefaultTimeout bounds one request attempt, body transfer included. Sized for the
	// largest the SDK sends — a 1 MiB WFP chunk — over a poor link.
	DefaultTimeout = 120 * time.Second
)

Defaults applied when the caller does not override them.

View Source
const DefaultScanChunkBytes = 1 << 20

Scan defaults applied when the corresponding option is not given. DefaultScanChunkBytes is the WFP upload block size (1 MiB).

View Source
const DefaultScanPollInterval = 2 * time.Second

DefaultScanPollInterval is the cadence for polling the scan status endpoint when the caller does not override it with WithPollInterval.

The server reports progress per pass, and polling samples it rather than streaming it: at a slower cadence a whole pass can come and go between two polls, leaving a progress display frozen for stretches that look like a hang.

Variables

View Source
var (
	ServiceComponentsSearch   = Service{Name: "components.search", /* contains filtered or unexported fields */}
	ServiceComponentsVersions = Service{Name: "components.versions", /* contains filtered or unexported fields */}
	ServiceComponentsStatus   = Service{Name: "components.status", /* contains filtered or unexported fields */}
	ServiceComponentStatus    = Service{Name: "component.status", /* contains filtered or unexported fields */}
)

Components service endpoints (v3): free-form search, version listing, and lifecycle status (single GET / batch POST share the same status path).

View Source
var (
	ServiceCopyrightEvidence = Service{Name: "copyright.evidence", /* contains filtered or unexported fields */}
	ServiceCopyrightHolders  = Service{Name: "copyright.holders", /* contains filtered or unexported fields */}
)

Copyright service endpoints (v3): per-file copyright evidence and the distinct set of copyright holders. Both accept one or many components in a single POST.

View Source
var (
	ServiceCryptographyAlgorithms        = Service{Name: "cryptography.algorithms", /* contains filtered or unexported fields */}
	ServiceCryptographyAlgorithm         = Service{Name: "cryptography.algorithm", /* contains filtered or unexported fields */}
	ServiceCryptographyAlgorithmsInRange = Service{Name: "cryptography.algorithms.range", /* contains filtered or unexported fields */}
	ServiceCryptographyAlgorithmInRange  = Service{Name: "cryptography.algorithm.range", /* contains filtered or unexported fields */}
	ServiceCryptographyVersionsInRange   = Service{Name: "cryptography.versions.range", /* contains filtered or unexported fields */}
	ServiceCryptographyVersionInRange    = Service{Name: "cryptography.version.range", /* contains filtered or unexported fields */}
	ServiceCryptographyHints             = Service{Name: "cryptography.hints", /* contains filtered or unexported fields */}
	ServiceCryptographyHint              = Service{Name: "cryptography.hint", /* contains filtered or unexported fields */}
	ServiceCryptographyHintsInRange      = Service{Name: "cryptography.hints.range", /* contains filtered or unexported fields */}
	ServiceCryptographyHintInRange       = Service{Name: "cryptography.hint.range", /* contains filtered or unexported fields */}
)

Cryptography service endpoints: algorithms and library hints, each for an exact version or a version range (plus algorithm versions in a range). Every variant has a batch (POST, many components) and a single (GET, one component) endpoint.

View Source
var (
	ServiceDependencies = Service{Name: "dependencies", /* contains filtered or unexported fields */}
	ServiceDependency   = Service{Name: "dependency", /* contains filtered or unexported fields */}
	ServiceTransitive   = Service{Name: "dependencies.transitive", /* contains filtered or unexported fields */}
)

Dependency service endpoints (v3): declared dependency + license resolution as a batch (POST, many components) and a single (GET, one component), plus a transitive walk bounded by depth and limit (POST).

View Source
var (
	ServiceGeoprovenanceOrigin       = Service{Name: "geoprovenance.origin", /* contains filtered or unexported fields */}
	ServiceGeoprovenanceOriginOne    = Service{Name: "geoprovenance.origin.one", /* contains filtered or unexported fields */}
	ServiceGeoprovenanceCountries    = Service{Name: "geoprovenance.countries", /* contains filtered or unexported fields */}
	ServiceGeoprovenanceCountriesOne = Service{Name: "geoprovenance.countries.one", /* contains filtered or unexported fields */}
)

Geoprovenance service endpoints: country of origin vs contributor countries, each as a batch (POST, many components) and a single (GET, one component) endpoint.

View Source
var (
	ServiceLicenseAttribution  = Service{Name: "license.attribution", /* contains filtered or unexported fields */}
	ServiceLicenseEvidence     = Service{Name: "license.evidence", /* contains filtered or unexported fields */}
	ServiceLicenses            = Service{Name: "licenses", /* contains filtered or unexported fields */}
	ServiceLicense             = Service{Name: "license", /* contains filtered or unexported fields */}
	ServiceLicensesDetails     = Service{Name: "licenses.details", /* contains filtered or unexported fields */}
	ServiceLicensesObligations = Service{Name: "licenses.obligations", /* contains filtered or unexported fields */}
)

License service endpoints (v3):

  • attribution / evidence: LICENSE-NOTICE files and per-file license evidence.
  • the License service under /v3/licenses: declared licenses for a component (single GET / batch POST), plus SPDX-registry details and OSADL obligations keyed by license id.
View Source
var (
	ServiceVulnerabilities   = Service{Name: "vulnerabilities", /* contains filtered or unexported fields */}
	ServiceVulnerability     = Service{Name: "vulnerability", /* contains filtered or unexported fields */}
	ServiceVulnerabilityCpes = Service{Name: "vulnerabilities.cpes", /* contains filtered or unexported fields */}
	ServiceVulnerabilityCpe  = Service{Name: "vulnerability.cpes", /* contains filtered or unexported fields */}
)

Vulnerability service endpoints: known vulnerabilities and CPEs, each as a batch (POST, many components) and a single (GET, one component) endpoint.

View Source
var ServiceScan = Service{Name: "scan", /* contains filtered or unexported fields */}

ServiceScan is the v3 batch scan endpoint. WFP fingerprints are uploaded as octet-stream byte ranges (Content-Range); the server assigns a scan id and queues the scan once all bytes are received.

Functions

func As

func As[T any](r *Result) (*T, error)

As decodes a Result's merged JSON document into the typed response T. The per-service methods use it to return the generated OpenAPI models; it is also exported for callers that hold a raw *Result.

Types

type ChunkError

type ChunkError struct {
	// Index is the zero-based position of the failed chunk.
	Index int
	// Err is the underlying error.
	Err error
}

ChunkError records the failure of a single chunk request.

func (ChunkError) Error

func (e ChunkError) Error() string

type Client

type Client struct {

	// Decoration services (grouped public API). Wired in New.
	Vulnerabilities VulnerabilityAPI
	Licenses        LicenseAPI
	Cryptography    CryptographyAPI
	Geoprovenance   GeoprovenanceAPI
	Copyright       CopyrightAPI
	Components      ComponentsAPI
	Dependencies    DependencyAPI

	// Scan service (batch WFP scanning). Wired in New.
	Scan ScanAPI
	// contains filtered or unexported fields
}

Client is the SCANOSS SDK entry point. Create one with New and reuse it; it is safe for concurrent use.

func New

func New(cfg Config) (*Client, error)

New creates a Client from cfg. It reports a configuration it cannot apply — an unreadable CA file, a proxy without a scheme — so a bad setting fails here instead of on the first request.

Example

Tuning chunk size and concurrency is done once at construction; the call site is unchanged.

package main

import (
	"context"

	"github.com/scanoss/scanoss.go/pkg/scanoss"
)

func main() {
	client, err := scanoss.New(scanoss.Config{
		APIKey:    "YOUR_API_KEY",
		ChunkSize: 20, // 20 PURLs per request
		Workers:   10, // up to 10 concurrent requests
	})
	if err != nil {
		panic(err)
	}

	comps := scanoss.Components("pkg:npm/lodash", "pkg:pypi/requests")

	// Each service is a single call; effective workers never exceed the chunk count.
	_, _ = client.Licenses.Attribution(context.Background(), comps)
	_, _ = client.Cryptography.Algorithms(context.Background(), comps)
	_, _ = client.Geoprovenance.Origins(context.Background(), comps)
}

func (*Client) DecorationPipeline

func (c *Client) DecorationPipeline(services ...Service) *DecorationPipeline

DecorationPipeline creates a pipeline bound to this client, seeded with the given services (deduped by name, order preserved).

Example

The pipeline runs a configurable set of decoration services in parallel over the same components, reports per-service progress, and returns one object keyed by service.

package main

import (
	"context"
	"fmt"

	"github.com/scanoss/scanoss.go/pkg/scanoss"
)

func main() {
	client, err := scanoss.New(scanoss.Config{APIKey: "YOUR_API_KEY", Workers: 10})
	if err != nil {
		panic(err)
	}

	pipe := client.DecorationPipeline(
		scanoss.ServiceVulnerabilities,
		scanoss.ServiceLicenses,
	)
	pipe.Add(scanoss.ServiceCryptographyAlgorithms, scanoss.ServiceGeoprovenanceOrigin)

	// scanoss.Components turns a list of PURLs into the []Component input.
	// The reporter travels with the call: every update carries the service that produced it, so one
	// receiver renders them all.
	res, err := pipe.Run(context.Background(),
		scanoss.Components("pkg:npm/lodash", "pkg:pypi/requests"),
		scanoss.WithDecorationReporter(serviceRows{}))
	if err != nil {
		panic(err)
	}

	fmt.Println(res.String()) // {"vulnerabilities":{...}, "licenses":{...}, ...}
	for svc, e := range res.Errors {
		fmt.Printf("%s failed: %v\n", svc, e)
	}
}

// serviceRows renders one line per decoration update. Services run concurrently, so a real
// implementation would guard whatever it draws into.
type serviceRows struct{}

func (serviceRows) Decorating(service string, done, total int) {
	fmt.Printf("%-26s %d/%d purls\n", service, done, total)
}

type Component

type Component struct {
	Purl        string `json:"purl"`
	Requirement string `json:"requirement,omitempty"`
}

Component is a single PURL (optionally pinned to a version requirement).

func Components

func Components(purls ...string) []Component

Components builds a []Component from PURL strings, with empty requirements. It accepts a slice via Components(purls...). For per-component version requirements, construct []Component{{Purl, Requirement}} directly. Blank entries are skipped.

type ComponentSearch

type ComponentSearch struct {
	Search    string // free-form term; overrides Vendor/Component when set
	Vendor    string
	Component string
	PurlType  string // purl type (github, npm, pypi, …); defaults to github server-side
	Limit     int    // max results (0 = server default)
	Offset    int    // pagination offset
}

ComponentSearch holds the filters for a component search. At least one of Search, Vendor or Component must be set; Search takes precedence when present.

type ComponentsAPI

ComponentsAPI is the components service surface. Responses are typed from the OpenAPI v3 contract.

type Config added in v0.6.0

type Config struct {
	// APIKey authenticates the requests. Empty means keyless, which the public
	// endpoint rejects and an on-prem one may allow.
	APIKey string
	// APIURL is the API base URL (default DefaultAPIURL). A trailing slash is trimmed.
	APIURL string

	// Proxy overrides HTTP_PROXY and HTTPS_PROXY for this client. It needs an http://
	// or https:// scheme; NO_PROXY still applies. Empty leaves Go's own environment
	// handling in place.
	Proxy string
	// CACertFile is a PEM file whose certificates are trusted in addition to the system
	// pool. Verification stays on: this adds an authority, it does not stop checking.
	CACertFile string
	// InsecureTLS disables certificate verification entirely. For self-signed or
	// internal endpoints only; prefer CACertFile, which keeps verification on.
	InsecureTLS bool
	// Timeout bounds one request attempt, body transfer included (default
	// DefaultTimeout). A negative value disables it. Retry-After waits happen between
	// attempts, so this does not cut them short.
	Timeout time.Duration

	// ChunkSize is the number of PURLs per decoration request (default
	// DefaultChunkSize), shared by every decoration service.
	ChunkSize int
	// Workers caps the concurrent requests (default DefaultWorkers). The effective
	// number is never larger than the number of chunks.
	Workers int
	// MaxRetries caps the retry count when the server answers 429/503 with a
	// Retry-After header (default DefaultMaxRetries).
	MaxRetries int
	// MaxRetryAfter caps a single Retry-After wait (default DefaultMaxRetryAfter),
	// bounding a pathological server value.
	MaxRetryAfter time.Duration

	// Logger receives the SDK's diagnostics, at Debug/Info/Warn (default
	// slog.Default()). The SDK never writes to stdout, only through this logger.
	Logger *slog.Logger
}

Config is the SDK's configuration. The zero value is the default configuration: every unset field falls back to its Default* constant.

type CopyrightAPI

type CopyrightAPI interface {
	Evidence(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.CopyrightEvidenceResponse, error)
	Holders(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.CopyrightHoldersResponse, error)
}

CopyrightAPI is the copyright service surface. Responses are typed from the OpenAPI v3 contract.

type CryptographyAPI

CryptographyAPI is the cryptography service surface: algorithms and library hints, each exact-version and version-range, plus algorithm versions in range. Responses are typed from the OpenAPI v3 contract.

type DecorateOption added in v0.5.0

type DecorateOption func(*decorateOptions)

DecorateOption configures a single decoration call. It is the decoration counterpart of ScanOption.

func WithDecorationReporter added in v0.5.0

func WithDecorationReporter(r DecorationReporter) DecorateOption

WithDecorationReporter reports this call's advance to r, service by service. Optional; by default the SDK reports nothing. Services run concurrently, so r must be safe for concurrent use.

type DecorationPipeline

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

DecorationPipeline runs a configurable set of decoration services over the same components, in parallel, and returns one result keyed by service. Create one with Client.DecorationPipeline and reuse it; configure the service set with Add/Remove.

func (*DecorationPipeline) Add

func (p *DecorationPipeline) Add(services ...Service) *DecorationPipeline

Add appends services that are not already present (dedupe by name). Chainable.

func (*DecorationPipeline) Remove

func (p *DecorationPipeline) Remove(services ...Service) *DecorationPipeline

Remove drops the named services if present. Chainable.

func (*DecorationPipeline) Run

func (p *DecorationPipeline) Run(ctx context.Context, components []Component, opts ...DecorateOption) (*PipelineResult, error)

Run queries every configured service concurrently over the same components and returns the combined result once all services have finished (success or failure). It is a barrier: Run returns only after the last service completes.

Run returns an error only if every service failed; otherwise it returns the PipelineResult with any per-service failures recorded in PipelineResult.Errors.

func (*DecorationPipeline) Services

func (p *DecorationPipeline) Services() []Service

Services returns a copy of the configured service set, in order.

type DecorationReporter added in v0.5.0

type DecorationReporter interface {
	// Decorating reports one service's advance over the components, counted in PURLs. Services run
	// concurrently, so updates from several arrive interleaved, each tagged with its own name
	// (Service.Name, e.g. "licenses" or "cryptography.algorithms").
	Decorating(service string, done, total int)
}

DecorationReporter receives enrichment progress: the components being gathered over, by service.

It is separate from ScanReporter because decoration needs no scan — an inventory parsed from a file is enriched the same way — and because there are consumers of each half alone: a command that only queries PURLs implements this and nothing else.

type DependencyAPI

type DependencyAPI interface {
	// Dependencies resolves declared dependencies + licenses for the given
	// components (batch POST).
	Dependencies(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.DependenciesResolveResponse, error)
	// Dependency resolves declared dependencies for a single component (GET).
	Dependency(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.DependenciesResolveResponse, error)
	// Transitive walks declared dependencies bounded by depth and limit (POST).
	// depth/limit <= 0 are omitted so the server defaults apply.
	Transitive(ctx context.Context, comps []Component, depth, limit int) (*scanossapi.TransitiveResponse, error)
}

DependencyAPI is the dependencies service surface. Responses are typed from the OpenAPI v3 contract; the compiler enforces that dependencyService implements every method (see the var _ below).

type GeoprovenanceAPI

type GeoprovenanceAPI interface {
	Origins(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.GeoOriginResponse, error)
	Origin(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.GeoOriginResponse, error)
	Countries(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.GeoContributorsResponse, error)
	Country(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.GeoContributorsResponse, error)
}

GeoprovenanceAPI is the geoprovenance service surface: country of origin and contributor countries, each batch and single. Responses are typed from the OpenAPI v3 contract.

type LicenseAPI

type LicenseAPI interface {
	Attribution(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.AttributionResponse, error)
	Evidence(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.LicenseEvidenceResponse, error)
	Components(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.ComponentsLicenseResponse, error)
	Component(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.ComponentLicenseResponse, error)
	Details(ctx context.Context, license string) (*scanossapi.LicenseDetailsResponse, error)
	Obligations(ctx context.Context, license string) (*scanossapi.ObligationsResponse, error)
}

LicenseAPI is the licenses service surface. Responses are typed from the OpenAPI v3 contract.

type PipelineResult

type PipelineResult struct {
	Services map[string]*Result // keyed by service name; full per-service result
	Errors   map[string]error   // services that failed entirely
}

PipelineResult holds each service's output, keyed by service name, plus any per-service failures.

func (*PipelineResult) MarshalJSON

func (pr *PipelineResult) MarshalJSON() ([]byte, error)

MarshalJSON renders the result as {"<service>": <merged response>, …}, where each value is that service's full merged response object.

func (*PipelineResult) String

func (pr *PipelineResult) String() string

String returns the pretty-printed keyed JSON.

type Result

type Result struct {

	// Failed lists the chunks that did not succeed, if any.
	Failed []ChunkError
	// contains filtered or unexported fields
}

Result holds the outcome of a chunked, multi-request query. Successful chunk responses are kept in input order; any per-chunk failures are reported in Failed (a partial result is still returned as long as at least one chunk succeeds).

func (*Result) Merged

func (r *Result) Merged() (json.RawMessage, error)

Merged combines the chunk responses into a single JSON document, concatenating top-level array fields (e.g. "components") across chunks and keeping the last value seen for scalar/object fields (e.g. "status").

func (*Result) Responses

func (r *Result) Responses() []json.RawMessage

Responses returns the raw JSON body of each successful chunk, in input order.

func (*Result) String

func (r *Result) String() string

String returns the merged document pretty-printed. It implements fmt.Stringer on a best-effort basis (returns an error marker if merging fails).

func (*Result) Unmarshal

func (r *Result) Unmarshal(v interface{}) error

Unmarshal decodes the merged JSON document into v.

type ScanAPI

type ScanAPI interface {
	// Folder collects, fingerprints and scans a directory tree (or single file).
	Folder(ctx context.Context, path string, opts ...ScanOption) (scanossapi.ScanEnvelope, error)

	// Files fingerprints and scans an explicit list of files.
	Files(ctx context.Context, files []string, opts ...ScanOption) (scanossapi.ScanEnvelope, error)

	// WFP scans an already-assembled WFP byte stream.
	WFP(ctx context.Context, wfp []byte, opts ...ScanOption) (scanossapi.ScanEnvelope, error)

	// Status performs a single status poll for a known scan id.
	Status(ctx context.Context, scanID string) (scanossapi.ScanEnvelope, error)

	// Wait resumes polling a known scan id until a terminal state. Used to recover
	// an interrupted scan (e.g. `scanoss-cli results <id>`). The poll cadence can be
	// tuned with WithPollInterval.
	Wait(ctx context.Context, scanID string, opts ...ScanOption) (scanossapi.ScanEnvelope, error)
}

ScanAPI is the batch scan service surface. Folder, Files and WFP each run the full flow — upload (parallel byte-range chunks) + poll to completion — and return the envelope with its Result populated. They differ only in the input: a directory tree, an explicit file list, or an already-assembled WFP. The caller never manages the scan id; stages are reported via WithScanReporter and the client-generated id is surfaced via WithScanIDNotify for optional recovery.

type ScanOption

type ScanOption func(*scanOptions)

ScanOption configures a single scan (Folder / Files / WFP).

func WithBOM

func WithBOM(bom *settings.BOM) ScanOption

WithBOM applies the scan's bill-of-materials rules to the result, post-scan and in order: bom.remove (with bom.include as precedence) neutralizes matching file matches, then bom.replace re-points the survivors it covers at their replace_with component; unreferenced components are pruned. The whole BOM is passed so the rules still to come (pre-scan include/identify context, ignore) extend this same option. A nil BOM is a no-op.

func WithChunkBytes

func WithChunkBytes(n int) ScanOption

WithChunkBytes sets the WFP upload block size in bytes (default DefaultScanChunkBytes). Values <= 0 are ignored.

func WithFilters

func WithFilters(f filter.Options) ScanOption

WithFilters sets the file-collection filters used by Folder: default skip lists, .gitignore and size bounds. The default is filter.ScanOptions(), which leaves Settings nil — pass scanoss.json rules here to have them applied.

func WithPollInterval

func WithPollInterval(d time.Duration) ScanOption

WithPollInterval sets how often the scan status endpoint is polled while waiting for a scan to finish (default DefaultScanPollInterval). Values <= 0 are ignored. Very small intervals increase load on the server. Applies to the full scan flow (Folder/Files/WFP) and to Wait when resuming a known scan id.

func WithScanIDNotify

func WithScanIDNotify(fn func(scanID string)) ScanOption

WithScanIDNotify registers a callback invoked once with this scan's id, after the full WFP is uploaded and before polling begins — the point from which Scan.Wait can resume it. Optional; a normal scan needs no recovery.

func WithScanReporter added in v0.5.0

func WithScanReporter(r ScanReporter) ScanOption

WithScanReporter reports this scan's stages to r. Optional; by default the SDK reports nothing.

It belongs to the call rather than to the Client on purpose: a Client is long-lived and shared — a caller may hand the same one to several operations, or to a library — while an observer belongs to the one operation it is watching.

type ScanReporter added in v0.5.0

type ScanReporter interface {
	// Fingerprinting reports local hashing as files are hashed. done only ever grows.
	Fingerprinting(done, total int)

	// Uploading reports WFP blocks handed to the server. done only ever grows: it counts 1..total,
	// one call per block, and the last call carries total.
	Uploading(done, total int)

	// Scanning reports one status poll of a running scan, handing over the server's envelope
	// verbatim: the SDK does not choose which of its fields matter.
	//
	// The server scans in passes ("Pass 1: scan files", "Pass 2: scan snippets", ...) that each
	// restart PhaseDone/PhaseTotal and count something different from the last, so those counters
	// are comparable only within one Phase. A caller rendering them as a single bar must segment it
	// by Phase; feeding them straight to one bar makes it run backwards.
	//
	// Polling samples the scan rather than streaming it, so a pass shorter than the poll interval
	// is never reported at all. Whether the scan succeeded is Status, never these counters.
	Scanning(env scanossapi.ScanEnvelope)
}

ScanReporter receives the stages of scanning a source tree, one method per stage. Each reports exactly what that stage has — the local ones a count, the server one its envelope — so no update's meaning depends on which other field happens to be set.

Which stages run depends on the entry point: Scan.WFP is handed its fingerprints already made and never reports Fingerprinting, and Scan.Wait resumes an uploaded scan, so it only reports Scanning. A stage that does not run simply never calls.

Register an implementation with WithScanReporter. Methods are called from whichever goroutine reached that stage — Uploading from the upload workers, so from several — but never two at once: the SDK serialises them, and each call happens before the next. An implementation therefore needs no lock of its own. It must not block, since a slow reporter holds up the stage reporting it.

type Service

type Service struct {
	Name string // stable id, used for logging/progress tagging
	// contains filtered or unexported fields
}

Service is a pure endpoint descriptor: a stable name and a REST path. It carries no request logic, so the same value serves the batch engine (decorate), the single path (decorateOne), and any future non-component endpoint (via do). Each value is declared in its own service file (e.g. ServiceVulnerabilities). Callers use the per-service methods on Client; the engine is internal.

type StatusError

type StatusError struct {
	StatusCode int
	Body       string
}

StatusError is returned by the transport when the API responds with a non-success status (anything outside the 2xx range). It exposes the status code so callers can branch on it (e.g. distinguish 401 Unauthorized) via errors.As.

func (*StatusError) Error

func (e *StatusError) Error() string

type VulnerabilityAPI

type VulnerabilityAPI interface {
	Components(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.VulnerabilitiesResponse, error)
	Component(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.VulnerabilitiesResponse, error)
	Cpes(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.CpesResponse, error)
	Cpe(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.CpesResponse, error)
}

VulnerabilityAPI is the vulnerabilities service surface. Responses are typed from the OpenAPI v3 contract; the compiler enforces that vulnerabilityService implements every method (see the var _ below).

Jump to

Keyboard shortcuts

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