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 ¶
- Constants
- Variables
- func As[T any](r *Result) (*T, error)
- type ChunkError
- type Client
- type Component
- type ComponentSearch
- type ComponentsAPI
- type Config
- type CopyrightAPI
- type CryptographyAPI
- type DecorateOption
- type DecorationPipeline
- func (p *DecorationPipeline) Add(services ...Service) *DecorationPipeline
- func (p *DecorationPipeline) Remove(services ...Service) *DecorationPipeline
- func (p *DecorationPipeline) Run(ctx context.Context, components []Component, opts ...DecorateOption) (*PipelineResult, error)
- func (p *DecorationPipeline) Services() []Service
- type DecorationReporter
- type DependencyAPI
- type GeoprovenanceAPI
- type LicenseAPI
- type PipelineResult
- type Result
- type ScanAPI
- type ScanOption
- type ScanReporter
- type Service
- type StatusError
- type VulnerabilityAPI
Examples ¶
Constants ¶
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.
const DefaultScanChunkBytes = 1 << 20
Scan defaults applied when the corresponding option is not given. DefaultScanChunkBytes is the WFP upload block size (1 MiB).
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 ¶
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).
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.
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.
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).
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.
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.
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.
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 ¶
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 ¶
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)
}
Output:
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)
}
Output:
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 ¶
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 ¶
type ComponentsAPI interface {
Search(ctx context.Context, q ComponentSearch) (*scanossapi.ComponentsSearchResponse, error)
Versions(ctx context.Context, purl string, limit int) (*scanossapi.ComponentVersionsResponse, error)
Status(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.ComponentsStatusResponse, error)
StatusOne(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.ComponentsStatusResponse, error)
}
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 ¶
type CryptographyAPI interface {
Algorithms(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.CryptoAlgorithmsResponse, error)
Algorithm(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.CryptoAlgorithmsResponse, error)
AlgorithmsInRange(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.CryptoAlgorithmsInRangeResponse, error)
AlgorithmInRange(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.CryptoAlgorithmsInRangeResponse, error)
VersionsInRange(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.CryptoVersionsInRangeResponse, error)
VersionInRange(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.CryptoVersionsInRangeResponse, error)
Hints(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.CryptoHintsResponse, error)
Hint(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.CryptoHintsResponse, error)
HintsInRange(ctx context.Context, comps []Component, opts ...DecorateOption) (*scanossapi.CryptoHintsInRangeResponse, error)
HintInRange(ctx context.Context, comp Component, opts ...DecorateOption) (*scanossapi.CryptoHintsInRangeResponse, error)
}
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.
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 ¶
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).