application

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package application orchestrates vulnerability scanning use cases.

It contains:

- ScanModuleUseCase — scans a single module: blob retrieval, snapshot resolution, scanner invocation, optional reachability, hashing, and persistence. - ScanWalkUseCase — scans every module in a walk. It runs a fail-fast scanner pre-flight, resolves and pre-extracts the database snapshot, pre-populates a shared GOMODCACHE, then dispatches a bounded worker pool. vuln-scan-rescan delegates here against a fresh snapshot. - Query/diff use cases — read-only access and scan-run comparison.

The layer depends only on the interfaces in vuln/ports and on pure vuln/domain logic for status aggregation and finding ordering; it performs no AST/zip parsing or external process execution itself — those are adapter concerns behind ports.VulnerabilityScanner.

Index

Constants

View Source
const PipelineVersion = "v19"

PipelineVersion identifies the vuln scan pipeline. It gates record reuse: a cached record is only reused when its PipelineVersion matches. It was bumped from "v1" when metadata-path findings began carrying advisory remediation detail (summary, affected range, fixed version, at-risk symbols) — cached metadata-only records from the old pipeline stored only the bare finding ID, so they are re-scanned and re-populated rather than served stale. It was bumped again to "v3" when scanner-reported Unscannable results (no go.mod, OOM kill) began routing through the OSV metadata path: a no-go.mod module cached under "v2" persisted a confident "no findings" even when advisories matched, so those records must be re-scanned rather than served stale. It was bumped to "v4" when a pre-populated GOMODCACHE began scanning with -mod=mod so the toolchain computes the go.sum entries a multi-module member's published go.sum omits for a cache-resolved sibling: modules cached under "v3" as Unscannable/missing-go-sum now resolve to a real source-level verdict and must be re-scanned rather than served stale. It was bumped to "v5" when the scan became hermetic (GOPROXY=off): resolution is pinned to the verified store, so a scan analyses only the versions the project's toolchain actually resolved, never a version fetched fresh from the network. Modules whose isolated build re-selects an out-of-toolchain version flip from a network-fabricated verdict to a truthful Unscannable (version-not-in-toolchain), so "v4" records must be re-scanned rather than served stale. It was bumped to "v6" when the scan environment began setting GOWORK=off: a module shipping a go.work in its published zip put the toolchain into workspace mode, which rejects the scan's -mod=mod and was recorded under "v5" as a misdiagnosed Unscannable/build-incompatible. Those modules now scan from source, so "v5" records must be re-scanned rather than served stale. It was bumped to "v7" when the hermetic cache began carrying the full transitive closure of superseded go.mod files: a pre-pruning (go<1.17) module needs that closure to load its module graph offline, and without it such modules were recorded under "v6" as metadata-only coverage gaps when they are in fact scannable from source. The same bump covers metadata-only records now retaining the originating toolchain error in error_detail, which "v6" records dropped. It was bumped to "v8" when a module zip carrying no go.mod began being scanned against a synthesised one: govulncheck's refusal is a precondition on the scan directory, not a property of the artefact, so modules recorded under "v7" as Unscannable/no-go-mod are in fact scannable from source and must be re-scanned rather than served stale. It was bumped to "v9" when advisory matching by coordinate became unconditional rather than a fallback from scan failure: a module scanned in isolation is govulncheck's main module and a main module has no version, so a successful source scan could never match an advisory about the module itself. Every "v8" Clean record produced by a successful scan is therefore an unchecked verdict rather than a confirmed one and must be re-scanned. It was bumped to "v10" when govulncheck's JSON stream began being framed by JSON value instead of by newline: govulncheck writes its messages indent-formatted, so a line-framed parse could never see a whole finding message and discarded every one of them. Every "v9" record was produced by a parse that reported no source findings at all — Clean verdicts that were never checked, and Affected verdicts missing their reachability and symbols — so all of them must be re-scanned. The same bump covers the project-rooted path, where advisory matching by coordinate is now unconditional rather than absent. It was bumped to "v11" when a coordinate-keyed walk began deriving its verdicts from a single scan rooted at the walk target instead of scanning each dependency in isolation: an isolated scan points `./...` at the dependency, loading every package it contains including ones no consumer can import, so a "v10" record could be a coverage gap caused by a package the target never builds, and its reachability was rooted at packages no consumer can reach. Every "v10" record on that path describes a different analysis and must be re-scanned. It was bumped to "v12" to correct the reachability of an advisory matched by coordinate on the walk target itself: the target is the versionless main module of the target-rooted analysis, which OSV matching structurally cannot reach a verdict on, so such a finding is now recorded with no reachability rather than a fabricated not-reachable/high-confidence. A "v11" record whose target is itself a vulnerable library carries that fabricated verdict and must be re-scanned; a walk whose target carries no advisory about itself is unaffected in content but re-scans under the new version like any other. It was bumped to "v13" when a version-not-in-toolchain verdict began being verified rather than asserted: the offline resolution failure's dominant shape attributes the failure to a source position and names no coordinate, so the incomplete-scan-cache check silently never ran and the reason was kept by default. Recovery now resolves the unimportable package to its module and reads the version the scanned module's own go.mod selects, and a failure whose version cannot be recovered is recorded as version-not-in-toolchain-unverified rather than an asserted out-of-toolchain outcome. A "v12" record on that path carries the unverified reason as if established and must be re-scanned. It was bumped to "v14" when the walk-scan aggregate gained separate coverage and findings axes: a WalkScanRun now stores CoverageStatus, FindingsStatus and the module counts alongside the collapsed OverallStatus, and a run recorded before the split carries neither axis, so a consumer that reads FindingsStatus off it silently loses the finding. The per-module record content is unchanged by this bump; the version moves so a walk scanned in the collapsed-status era re-runs as a whole and produces a run carrying both axes, rather than reusing cached per-module verdicts under a run that has neither. It was bumped to "v15" when two record-shape changes landed together, both of which alter the canonical bytes a record hashes over.

First, the per-module record gained the same two verdict axes the walk-scan aggregate got at v14: CoverageStatus and FindingsStatus now sit beside the collapsed OverallStatus, whose four values answered two different questions. The projection is total and lossless, so a "v14" record loses nothing — migration 11 back-fills the columns and RecordAxes recovers the axes on read — but a record written from v15 onward carries them in its blob and therefore hashes differently.

Second, DatabaseSnapshot.ContentHash is now populated. It was already part of the record's canonical shape and was empty on every record ever written, so the advisory database — the evidence every finding is derived from — was the one input to a verdict that could not be checked against the bytes it was reached from. Populating it changes stored record hashes; migration 10 seals the snapshot blobs the store already holds so an existing store can verify them too.

It was bumped to "v16" when a withdrawn advisory stopped being reported as a finding against the module it names. The OSV top-level "withdrawn" timestamp is now parsed — on both the metadata path and the govulncheck stream — carried on the finding as WithdrawnAt, and read by the findings axis, which gained a third value: a module whose every matched advisory is retracted reports Withdrawn rather than Affected, and never Clean.

The bump is what makes the fix reachable, not merely a shape formality. A "v15" record for a coordinate carrying a retracted advisory holds an Affected verdict reached before the retraction could be read, and its withdrawal is not recoverable from the record — WithdrawnAt was never populated, so no migration can correct it in place. Without the bump those records would be reused from cache and the false positive would survive the fix. Under it, a re-scan produces a v16 record that states the retraction, and the v15 record remains readable as what the earlier generation concluded.

The record's canonical bytes are unchanged for every finding that is not withdrawn: WithdrawnAt is a new field carrying omitzero, so it is absent from the encoding exactly when it is zero, and a v15 record's hash recomputes identically under this generation.

It was bumped to "v17" when a govulncheck trace consisting entirely of package-initialisation frames stopped being ingested as a reachability route.

Where an advisory entry names no symbols for a module path, govulncheck treats the whole package as vulnerable and the only thing it can report is that the package's own init ran — which follows from the package being linked into the build, not from anything calling the vulnerable code. Those frames were read as a route, so the finding was recorded reachable at High confidence with source fidelity, and "init" was written into affected_symbols, a symbol no advisory ever names. Such a finding is now recorded as affected at package level: no route, no symbol, IsReachable false at Confidence Unknown — the store's existing "not determined" value — and the new AdvisoryNamesNoSymbols field states why, so the absent route is not read as "nothing calls it". The coordinate match is untouched; the module remains Affected.

The bump is what makes the fix reachable rather than a shape formality. A "v16" record for such a coordinate asserts reachable/High over init frames, and the claim is not correctable in place: the verdict and the route are both inside the hashed canonical shape, so rewriting them would require re-sealing a v16 record against evidence the earlier generation reached a different conclusion from — the mistake migration 10 was withdrawn for. Read-side queries pin to this constant, so under the bump those records stop being served and a re-scan produces a v17 record that states the package-level match, while the v16 row remains readable in the ledger as what the earlier generation concluded. Without the bump the false reachable claim would survive the fix from cache. Measured on a working store: github.com/golang-jwt/jwt@v3.2.2+incompatible and github.com/golang-jwt/jwt/v4@v4.5.1 both carried GO-2025-3553 as reachable/High in the same run, and only the second had a route to the advisory's named symbol.

The record's canonical bytes are unchanged for every finding this does not re-classify: AdvisoryNamesNoSymbols is a new field carrying omitzero, so it is absent from the encoding exactly when it is false, and an untouched v16 record's hash recomputes identically under this generation.

It was bumped to "v18" when a reachability analysis that was requested and failed stopped being recorded as though it had never been requested.

The failure was logged at WARN and the finding kept a nil Reachable, which is also what a scan run without --reachability leaves behind. The two are indistinguishable in the record, so the read side attributed the absence to a missing flag and advised re-running with a flag that had been passed, while the scan exited 0 and reported its finding set as though reachability had not been needed. The failure now travels with the finding as a ReachabilityNote naming the reason, and the read side names that cause instead of assuming one.

The bump is what makes the fix reachable rather than a shape formality. A "v17" record on that path carries a nil Reachable and no note, and nothing in it records that the question was ever asked — so no migration can tell it apart from a record where it genuinely was not. Read-side queries pin to this constant, so under the bump those records stop being served and a re-scan either computes the reachability the same run can now load, or records why it could not; the v17 rows remain readable in the ledger as what the earlier generation concluded. Without the bump the silent degradation would survive the fix from cache. Measured on a working store: a 128-module walk scanned with --reachability reported Affected (14) with reachability unavailable and unstated for the findings a security review had called auth-critical.

No shape change and no migration is owed with it. ReachabilityNote is an existing hashed field already populated on the callgraph-spawn-failure path, carrying omitzero, so it is absent from the encoding exactly when it is empty and an untouched v17 record's hash recomputes identically under this generation. v19 records the analysis surface — which copy of a module's source the run resolved from — and, for a vendored project, changes which copy that is.

The behavioural half is what forces the bump rather than the field. A project carrying vendor/modules.txt is now analysed under -mod=vendor from the tree it compiles, where a v18 run resolved the same build from the artefacts kanonarion fetched. Those can differ — detecting exactly that divergence is the tool's own value proposition — so a re-scan of unchanged inputs can now produce a different verdict for the same coordinate under the same snapshot. Read-side queries pin to this constant, so without the bump the fetched-surface v18 row would keep answering the vendored-surface question, and the run that finally read the built bytes would be served the one that did not.

The field is the other half and could not have carried the bump on its own: analysis_surface is omitempty, so an untouched v18 record still recomputes its hash identically under this generation, and the ledger's older rows stay readable as what the earlier generation concluded.

No migration is owed. Reads are keyed on the pipeline version, so the v18 rows are already unreachable for a v19 question, and the surface lives inside the serialised record rather than in a column, so no schema changes. Purging them would cost every store an irreversible schema bump to delete rows nothing can read. The cost that IS owed is a full re-scan before a store can answer at v19, which is the price of no longer serving a verdict about the wrong bytes.

Variables

This section is empty.

Functions

This section is empty.

Types

type DiffScanRunsUseCase

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

DiffScanRunsUseCase compares two WalkScanRuns of the same walk.

func NewDiffScanRunsUseCase

func NewDiffScanRunsUseCase(vulnStore ports.VulnerabilityStore) *DiffScanRunsUseCase

NewDiffScanRunsUseCase returns a new DiffScanRunsUseCase.

func (*DiffScanRunsUseCase) Diff

func (uc *DiffScanRunsUseCase) Diff(ctx context.Context, runIDA, runIDB string) (domain.ScanRunDiff, error)

Diff loads scan runs A and B plus their vulnerability records, then delegates the comparison to domain.DiffScanRuns.

type QueryScanRunsUseCase

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

QueryScanRunsUseCase provides read-only access to walk scan runs and database snapshots.

func NewQueryScanRunsUseCase

func NewQueryScanRunsUseCase(store ports.VulnerabilityStore) *QueryScanRunsUseCase

NewQueryScanRunsUseCase constructs a QueryScanRunsUseCase.

func (*QueryScanRunsUseCase) GetLatestSnapshot

func (uc *QueryScanRunsUseCase) GetLatestSnapshot(ctx context.Context) (domain.DatabaseSnapshot, bool, error)

GetLatestSnapshot returns the most recently stored snapshot metadata.

func (*QueryScanRunsUseCase) GetRun

GetRun retrieves a walk scan run by its ID.

func (*QueryScanRunsUseCase) ListAllRuns

func (uc *QueryScanRunsUseCase) ListAllRuns(ctx context.Context) ([]domain.WalkScanRun, error)

ListAllRuns returns all scan runs across all walks, most recent first, on the same partial-result terms as ListRunsForWalk.

func (*QueryScanRunsUseCase) ListRunsForWalk

func (uc *QueryScanRunsUseCase) ListRunsForWalk(ctx context.Context, walkID string) ([]domain.WalkScanRun, error)

ListRunsForWalk returns all scan runs for the given walk ID.

The runs the store could verify are returned even when it also reports rows it could not — see ports.UnreadableRuns. Discarding them here would put the choice beyond every caller's reach: a survey command could then only print a list that omits the faulty rows without saying so, or nothing at all.

func (*QueryScanRunsUseCase) ListSnapshots

func (uc *QueryScanRunsUseCase) ListSnapshots(ctx context.Context) ([]domain.DatabaseSnapshot, error)

ListSnapshots returns all stored vulnerability database snapshot metadata, most recent first.

type QueryVulnUseCase

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

QueryVulnUseCase provides read-only access to vulnerability records.

func NewQueryVulnUseCase

func NewQueryVulnUseCase(store ports.VulnerabilityStore) *QueryVulnUseCase

NewQueryVulnUseCase constructs a QueryVulnUseCase.

func (*QueryVulnUseCase) GetLatestRecord

func (uc *QueryVulnUseCase) GetLatestRecord(
	ctx context.Context,
	coord coordinate.ModuleCoordinate,
	pipelineVersion string,
) (domain.VulnerabilityRecord, bool, error)

GetLatestRecord returns the most recently scanned record for a coordinate and pipeline version.

func (*QueryVulnUseCase) GetLatestRecordForWalk

func (uc *QueryVulnUseCase) GetLatestRecordForWalk(
	ctx context.Context,
	coord coordinate.ModuleCoordinate,
	pipelineVersion string,
	walkID string,
) (domain.VulnerabilityRecord, bool, error)

GetLatestRecordForWalk returns the most recently scanned record for a coordinate, pipeline version, and walk ID.

func (*QueryVulnUseCase) GetRecord

func (uc *QueryVulnUseCase) GetRecord(
	ctx context.Context,
	coord coordinate.ModuleCoordinate,
	pipelineVersion string,
	snapshot domain.DatabaseSnapshot,
) (domain.VulnerabilityRecord, bool, error)

GetRecord retrieves a vulnerability record by coordinate, pipeline version, and snapshot.

func (*QueryVulnUseCase) ListRecordsByFindingID

func (uc *QueryVulnUseCase) ListRecordsByFindingID(ctx context.Context, findingID, walkID string) ([]domain.VulnerabilityRecord, error)

ListRecordsByFindingID returns the vulnerability records containing a finding with the given ID. An empty walkID spans the whole store; a non-empty one restricts the answer to the modules that walk's scan runs covered.

func (*QueryVulnUseCase) ListRecordsForModule

func (uc *QueryVulnUseCase) ListRecordsForModule(
	ctx context.Context,
	coord coordinate.ModuleCoordinate,
	pipelineVersion string,
) ([]domain.VulnerabilityRecord, error)

ListRecordsForModule returns all stored scan records for a coordinate and pipeline version.

type RescanRequest

type RescanRequest struct {
	WalkID             string
	Snapshot           *domain.DatabaseSnapshot // nil = take a fresh snapshot from the network
	EnableReachability bool
	Operator           string
}

RescanRequest defines the input for a re-scan operation.

type RescanWalkUseCase

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

RescanWalkUseCase re-runs a vulnerability scan for an existing walk against a fresh (or explicitly pinned) database snapshot, producing a new WalkScanRun without modifying any prior scan runs.

func NewRescanWalkUseCase

func NewRescanWalkUseCase(
	walkStore walkports.WalkStore,
	vulnStore ports.VulnerabilityStore,
	moduleScanner *ScanModuleUseCase,
	fetcher ports.ModuleFetcher,
	clock fetchports.Clock,
	pipelineVersion string,
	logger *slog.Logger,
) *RescanWalkUseCase

func (*RescanWalkUseCase) Rescan

Rescan performs the re-scan scan and returns the new WalkScanRun. It always forces a fresh scan (bypassing per-module cache) so that the new snapshot is actually consulted, and it never modifies existing scan runs.

func (*RescanWalkUseCase) WithAudit

func (uc *RescanWalkUseCase) WithAudit(sink ports.AuditSink) *RescanWalkUseCase

WithAudit wires an audit sink that the delegated walk scan uses to append assurance-log events. Optional (nil disables emission); returns the receiver for chaining.

func (*RescanWalkUseCase) WithHostMemory added in v0.6.0

func (uc *RescanWalkUseCase) WithHostMemory(mem ports.HostMemory) *RescanWalkUseCase

WithHostMemory propagates the host-memory reporter to the delegated walk scan, so a re-scan sizes its module-scan pool against the same memory budget a first scan does. Optional (nil keeps the CPU-only cap); returns the receiver for chaining.

func (*RescanWalkUseCase) WithRealModcache added in v0.2.0

func (uc *RescanWalkUseCase) WithRealModcache(dir string) *RescanWalkUseCase

WithRealModcache propagates --from-modcache to the delegated walk scan, so the re-scan reads govulncheck's dependencies from the existing module cache at dir instead of a blob-store-populated temp cache. Empty (the default) keeps the blob-store path. Returns the receiver for chaining.

func (*RescanWalkUseCase) WithVCSHosts added in v0.6.0

NewRescanWalkUseCase returns a new RescanWalkUseCase. WithVCSHosts sets the effective VCS forge allowlist for the pre-fetch the delegated scan may perform. A rescan re-runs the same pipeline, so it must be bound by the same policy; leaving it out would restore the divergence this exists to remove, one command over.

type ScanModuleParams

type ScanModuleParams struct {
	Coordinate         coordinate.ModuleCoordinate
	WalkID             string
	Snapshot           *domain.DatabaseSnapshot // nil = use latest
	Force              bool
	EnableReachability bool
	GoModCache         string          // pre-populated GOMODCACHE dir; empty = govulncheck downloads as needed
	VulnDBDir          string          // pre-extracted vuln DB dir; empty = extract from store on each call
	ScanMode           domain.ScanMode // source or binary; empty defaults to source
	// CallGraphSem is a shared semaphore that limits concurrent callgraph subprocess
	// spawns across all module scans in the same walk. nil means no concurrency limit.
	CallGraphSem chan struct{}
	// KnownVersions is the set of module versions the walk knows this scan may
	// need: its nodes plus the superseded requirements recorded on its edges. It
	// discriminates the two ways an offline resolution can fail. A version in
	// this set was one kanonarion undertook to supply, so failing to resolve it
	// is an incomplete scan cache — a fault. A version outside it was selected by
	// the module's own isolated build and never belonged to the project's
	// toolchain, which is the expected consequence of hermetic scanning. Built
	// once per walk and read concurrently; never written during a scan. A nil map
	// disables the discrimination and every failure reads as out-of-toolchain,
	// preserving the behaviour of callers that scan without a graph.
	KnownVersions map[coordinate.ModuleCoordinate]struct{}
	// SelectedVersions is the set of module versions the walk actually fetched —
	// one per node, always the version the project's build selected. It seeds the
	// require directives of a go.mod synthesised for a module zip published
	// before Go modules, so the isolated scan resolves the project's own
	// versions. It is deliberately not KnownVersions: that set also carries the
	// coordinate a replaced node stands in for, which names a module whose source
	// was never fetched, and requiring it would fail every scan that used it.
	SelectedVersions map[coordinate.ModuleCoordinate]struct{}
}

ScanModuleParams defines the input for a module scan.

type ScanModuleUseCase

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

ScanModuleUseCase orchestrates a single module's vulnerability scan.

func NewScanModuleUseCase

func NewScanModuleUseCase(
	factStore fetchports.FactStore,
	blobs fetchports.BlobStore,
	vulnStore ports.VulnerabilityStore,
	walkStore walkports.WalkStore,
	scanner ports.VulnerabilityScanner,
	database ports.VulnerabilityDatabase,
	reachability ports.ReachabilityAnalyser,
	clock fetchports.Clock,
	pipelineVersion string,
	logger *slog.Logger,
) *ScanModuleUseCase

NewScanModuleUseCase returns a new ScanModuleUseCase.

func (*ScanModuleUseCase) Preflight

func (uc *ScanModuleUseCase) Preflight(ctx context.Context) error

Preflight delegates to the underlying scanner's availability check so a walk-wide scan can fail fast before any expensive setup.

func (*ScanModuleUseCase) Scan

Scan performs the scan.

func (*ScanModuleUseCase) WithCallGraphLoader

func (uc *ScanModuleUseCase) WithCallGraphLoader(loader ports.CallGraphLoader) *ScanModuleUseCase

WithCallGraphLoader sets the loader used to retrieve call graph records for reachability analysis. Returns the receiver for chaining.

func (*ScanModuleUseCase) WithCallGraphSpawner

func (uc *ScanModuleUseCase) WithCallGraphSpawner(spawner ports.CallGraphSpawner) *ScanModuleUseCase

WithCallGraphSpawner sets the spawner used to run on-demand callgraph extraction subprocesses for modules with findings but no cached callgraph. Returns the receiver for chaining.

type ScanWalkParams

type ScanWalkParams struct {
	WalkID             string
	Snapshot           *domain.DatabaseSnapshot // nil = use latest
	Force              bool
	Fresh              bool
	EnableReachability bool
	Operator           string
	// Workers controls the module scan pool size. Zero means the derived cap:
	// min(NumCPU, 4) further reduced by the host's available-memory budget (see
	// resolveWorkerCount). A non-zero value is an explicit operator override and
	// is taken as given — the memory budget does not second-guess it.
	Workers int
	// CallGraphWorkers limits concurrent on-demand callgraph subprocess spawns.
	// Zero defaults to 1. Kept separate from Workers because SSA builds are
	// memory-heavy while scan workers are I/O-bound; mixing them would allow
	// N concurrent SSA loads.
	CallGraphWorkers int
	// BinaryModePrePass runs a fast binary-mode scan first; only modules flagged as
	// Affected then receive the full (slow) source-mode scan for call-graph precision.
	BinaryModePrePass bool
	// ProjectDir is the project's working-tree directory (the one holding go.mod).
	// When set and the walk is rooted at the local main module, the scan is
	// project-rooted: one govulncheck over the live tree derives a per-module
	// verdict for the whole build, instead of scanning each dependency in
	// isolation. Empty on a coordinate-keyed walk, which roots the same kind of
	// single analysis at the walk target's own zip instead.
	ProjectDir string
	// NoVendor forces the fetched surface for a project that carries a
	// vendor/ tree, which would otherwise be analysed from the vendored source
	// it compiles. It exists for comparison — running both surfaces over one
	// project is how a divergence between the vendored tree and the fetched
	// artefacts becomes visible — and never as a default.
	NoVendor bool
	// Progress is called after each module is scanned. It may be nil.
	Progress func(coord coordinate.ModuleCoordinate, record domain.VulnerabilityRecord, current, total int)
}

ScanWalkParams defines the input for a walk scan.

type ScanWalkUseCase

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

ScanWalkUseCase orchestrates a walk-wide vulnerability scan.

func NewScanWalkUseCase

func NewScanWalkUseCase(
	walkStore walkports.WalkStore,
	vulnStore ports.VulnerabilityStore,
	moduleScanner *ScanModuleUseCase,
	fetcher ports.ModuleFetcher,
	clock fetchports.Clock,
	pipelineVersion string,
	logger *slog.Logger,
) *ScanWalkUseCase

func (*ScanWalkUseCase) Scan

Scan performs the walk-wide scan.

func (*ScanWalkUseCase) WithAudit

func (uc *ScanWalkUseCase) WithAudit(sink ports.AuditSink) *ScanWalkUseCase

WithAudit wires an audit sink so the scan appends assurance-log events: one vuln_scan_completed per run and one vuln_finding_observed per finding. It is optional — a nil sink (the default) disables emission — and returns the receiver for chaining, mirroring the other optional-dependency builders.

func (*ScanWalkUseCase) WithHostMemory added in v0.6.0

func (uc *ScanWalkUseCase) WithHostMemory(mem ports.HostMemory) *ScanWalkUseCase

WithHostMemory wires the host-memory reporter the module-scan pool sizes itself against. It is optional — a nil reporter (the default) leaves the pool on its CPU-only cap — and returns the receiver for chaining, mirroring the other optional-dependency builders.

func (*ScanWalkUseCase) WithRealModcache added in v0.2.0

func (uc *ScanWalkUseCase) WithRealModcache(dir string) *ScanWalkUseCase

WithRealModcache switches the scan into --from-modcache mode: govulncheck runs with GOMODCACHE pointed at dir, an already-populated module cache, instead of materialising a temp cache from the blob store. A nil/empty dir (the default) keeps the blob-store-populated path. Returns the receiver for chaining.

func (*ScanWalkUseCase) WithVCSHosts added in v0.6.0

WithVCSHosts sets the effective VCS forge allowlist for the pre-fetch this scan may perform.

It exists because a vuln-scan that finds a module missing from the fact store fetches it, and that fetch cross-verifies against a forge. Without this the allowlist a run applies depended on which command happened to populate the store first: walk and audit bound by the operator's policy, vuln-scan not bound at all.

func (*ScanWalkUseCase) WithVendoredClosure added in v0.7.0

func (uc *ScanWalkUseCase) WithVendoredClosure(r ports.VendoredClosureReader) *ScanWalkUseCase

WithVendoredClosure wires the reader that tells the scan which modules a vendored project's tree holds. It is optional — a nil reader (the default) keeps every scan on the fetched surface — and returns the receiver for chaining, mirroring the other optional-dependency builders.

Jump to

Keyboard shortcuts

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