store

package
v0.0.0-...-0979862 Latest Latest
Warning

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

Go to latest
Published: Apr 27, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package store provides SQLite database access for benchmrk.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is returned when a requested entity does not exist.

ValidAnnotationStatuses lists all allowed annotation status values.

ValidDispositions lists all allowed disposition values.

View Source
var ValidGroupRoles = []string{"source", "sink", "related"}

ValidGroupRoles lists allowed group member roles.

Functions

func IsValidAnnotationStatus

func IsValidAnnotationStatus(status AnnotationStatus) bool

IsValidAnnotationStatus checks if a status string is valid.

func IsValidDisposition

func IsValidDisposition(d Disposition) bool

IsValidDisposition checks if a disposition string is valid.

func IsValidGroupRole

func IsValidGroupRole(role string) bool

IsValidGroupRole checks if a role string is valid.

Types

type Annotation

type Annotation struct {
	ID          int64
	ProjectID   int64
	FilePath    string
	StartLine   int
	EndLine     sql.NullInt64
	CWEID       sql.NullString
	Category    string
	Severity    string
	Description sql.NullString
	Status      AnnotationStatus
	AnnotatedBy sql.NullString
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

Annotation represents a ground-truth vulnerability annotation in a project.

type AnnotationGroup

type AnnotationGroup struct {
	ID        int64
	ProjectID int64
	Name      sql.NullString
	CreatedAt time.Time
}

AnnotationGroup represents a logical grouping of related annotations.

type AnnotationGroupMember

type AnnotationGroupMember struct {
	GroupID      int64
	AnnotationID int64
	Role         string // "source", "sink", "related"
}

AnnotationGroupMember represents membership of an annotation in a group.

type AnnotationSet

type AnnotationSet struct {
	ID         int64
	ProjectID  int64
	Hash       string
	SourcePath sql.NullString
	GitSHA     sql.NullString
	VulnCount  int
	Format     string // import-format tag written by the importer
	ImportedAt time.Time
}

AnnotationSet records one import of an annotation file. The hash joins to runs.annotation_hash so you can recover "which file produced the ground truth this run was scored against."

type AnnotationStatus

type AnnotationStatus string

AnnotationStatus is the validity state of a ground-truth annotation.

const (
	AnnotationStatusValid    AnnotationStatus = "valid"
	AnnotationStatusInvalid  AnnotationStatus = "invalid"
	AnnotationStatusDisputed AnnotationStatus = "disputed"
)

type CorpusProject

type CorpusProject struct {
	ID        int64
	Name      string
	SourceURL sql.NullString
	LocalPath string
	Language  sql.NullString
	CommitSHA sql.NullString
	CreatedAt time.Time
}

CorpusProject represents a project in the corpus that we scan.

type Disposition

type Disposition string

Disposition is a human triage judgment on a finding.

const (
	DispositionTP          Disposition = "tp"
	DispositionFP          Disposition = "fp"
	DispositionNeedsReview Disposition = "needs_review"
)

type Evidence

type Evidence struct {
	ID        int64
	VulnID    int64
	FilePath  string
	StartLine int
	EndLine   sql.NullInt64
	Role      string // sink | source | helper | related — informational
	Category  string
	Severity  string
	CreatedAt time.Time
}

Evidence is one location where a vulnerability manifests. The matcher works at this granularity — findings match evidence rows, not vulns — and metrics rolls evidence matches up to vulnerability satisfaction.

IDs inherit from the old annotations table (migration 010 preserved them) so the compat shim's GetAnnotation(id) is a direct lookup.

type ExecutionMode

type ExecutionMode string

ExecutionMode describes how a scanner is invoked.

const (
	ExecutionModeDocker ExecutionMode = "docker"
	ExecutionModeLocal  ExecutionMode = "local"
)

type Experiment

type Experiment struct {
	ID          int64
	Name        string
	Description sql.NullString
	Iterations  int
	CreatedAt   time.Time
}

Experiment represents a benchmarking experiment configuration.

type Finding

type Finding struct {
	ID          int64
	RunID       int64
	RuleID      sql.NullString
	FilePath    string
	StartLine   int
	EndLine     sql.NullInt64
	CWEID       sql.NullString
	Severity    sql.NullString
	Message     sql.NullString
	Snippet     sql.NullString
	Fingerprint sql.NullString
	CreatedAt   time.Time
}

Finding represents a parsed finding from scanner output.

type FindingDisposition

type FindingDisposition struct {
	ID          int64
	FindingID   int64
	Disposition Disposition
	Notes       sql.NullString
	ReviewedBy  sql.NullString
	CreatedAt   time.Time
}

FindingDisposition records a human triage judgment on an unmatched finding.

type FindingMatch

type FindingMatch struct {
	ID        int64
	FindingID int64
	// AnnotationID is stored in the evidence_id column post migration 010.
	// The Go name stays so the matcher, metrics, and analysis code keep
	// compiling — and semantically it IS still "the annotation this finding
	// matched" since evidence row IDs inherit from the old annotation IDs.
	// New code should think of this as an evidence ID; the name is compat.
	AnnotationID int64
	MatchType    string
	Confidence   sql.NullFloat64
	CreatedAt    time.Time
}

FindingMatch represents a match between a finding and a ground-truth annotation.

type Run

type Run struct {
	ID              int64
	ExperimentID    int64
	ScannerID       int64
	ProjectID       int64
	Iteration       int
	Status          RunStatus
	StartedAt       sql.NullTime
	CompletedAt     sql.NullTime
	DurationMs      sql.NullInt64
	MemoryPeakBytes sql.NullInt64
	SarifPath       sql.NullString
	LogPath         sql.NullString
	ErrorMessage    sql.NullString
	// Scorer pinning — stamped at MatchRun time, not experiment-run time.
	// The scorer that matters is the one that produced finding_matches.
	// NULL on rows scored before migration 009.
	MatcherVersion sql.NullString
	AnnotationHash sql.NullString
	CreatedAt      time.Time
}

Run represents a single scan execution.

type RunStatus

type RunStatus string

RunStatus is the lifecycle state of a scan run.

const (
	RunStatusPending   RunStatus = "pending"
	RunStatusRunning   RunStatus = "running"
	RunStatusCompleted RunStatus = "completed"
	RunStatusFailed    RunStatus = "failed"
)

type Scanner

type Scanner struct {
	ID             int64
	Name           string
	Version        string
	DockerImage    string
	ConfigJSON     sql.NullString
	ExecutionMode  ExecutionMode  // ExecutionModeDocker or ExecutionModeLocal
	ExecutablePath sql.NullString // path to local executable (when execution_mode = "local")
	CreatedAt      time.Time
}

Scanner represents a registered SAST scanner.

type Store

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

Store wraps a SQLite database connection.

func New

func New(dbPath string) (*Store, error)

New opens a SQLite database at the given path with WAL mode and foreign keys enabled. Use ":memory:" for an in-memory database.

func (*Store) AddAnnotationToGroup

func (s *Store) AddAnnotationToGroup(ctx context.Context, groupID, annotationID int64, role string) error

func (*Store) AddProjectToExperiment

func (s *Store) AddProjectToExperiment(ctx context.Context, experimentID, projectID int64) error

AddProjectToExperiment links a project to an experiment.

func (*Store) AddScannerToExperiment

func (s *Store) AddScannerToExperiment(ctx context.Context, experimentID, scannerID int64) error

AddScannerToExperiment links a scanner to an experiment.

func (*Store) AddVulnAnnotator

func (s *Store) AddVulnAnnotator(ctx context.Context, vulnID int64, annotatedBy string) error

func (*Store) AddVulnCWE

func (s *Store) AddVulnCWE(ctx context.Context, vulnID int64, cweID string) error

func (*Store) AnnotationHash

func (s *Store) AnnotationHash(ctx context.Context, projectID int64) (string, error)

AnnotationHash computes a stable digest of the project's ground truth. Two runs with different hashes were graded against different annotation sets and their metrics are not comparable.

Covers every field the matcher and ComputeVulnMetrics read: vulnerability name/status/criticality, evidence location/category/ severity, CWE set. Excludes description, annotators, timestamps — edits that don't affect scoring shouldn't churn the hash.

Stable across insert order: everything is sorted before hashing, and IDs are resolved to positions so two DBs with the same content inserted differently hash the same.

func (*Store) BulkCreateAnnotations

func (s *Store) BulkCreateAnnotations(ctx context.Context, annotations []Annotation) error

BulkCreateAnnotations inserts N single-evidence vulns in one transaction via the Annotation compat type. Retained alongside the Annotation shim for one-row-at-a-time callers; the file-import path uses BulkCreateVulnerabilities directly.

func (*Store) BulkCreateFindings

func (s *Store) BulkCreateFindings(ctx context.Context, findings []Finding) error

BulkCreateFindings inserts multiple findings in a single transaction. If any insert fails, the entire batch is rolled back.

func (*Store) BulkCreateVulnerabilities

func (s *Store) BulkCreateVulnerabilities(ctx context.Context, vulns []VulnWithDetail) error

BulkCreateVulnerabilities inserts a set of vulnerabilities with their evidence, CWEs, and annotators in one transaction. This is the sole file-import path.

func (*Store) ClearFindingMatchesForRun

func (s *Store) ClearFindingMatchesForRun(ctx context.Context, runID int64) (int64, error)

ClearFindingMatchesForRun deletes every finding_matches row produced by a run's findings. This is derived state — the findings themselves are untouched — so the next MatchRun call will recompute from scratch and re-stamp the run's matcher_version and annotation_hash. Returns the number of rows deleted.

func (*Store) Close

func (s *Store) Close() error

Close closes the database connection.

func (*Store) CreateAnnotation

func (s *Store) CreateAnnotation(ctx context.Context, a *Annotation) (int64, error)

CreateAnnotation creates a single-evidence vulnerability and returns the evidence row's ID — which callers treat as "the annotation ID" exactly as before. The vulnerability name is synthesized from category + location, matching what migration 010 did for solo annotations.

func (*Store) CreateAnnotationGroup

func (s *Store) CreateAnnotationGroup(ctx context.Context, g *AnnotationGroup) (int64, error)

func (*Store) CreateDisposition

func (s *Store) CreateDisposition(ctx context.Context, d *FindingDisposition) (int64, error)

CreateDisposition inserts or replaces a finding disposition and returns its ID.

func (*Store) CreateEvidence

func (s *Store) CreateEvidence(ctx context.Context, e *Evidence) (int64, error)

func (*Store) CreateExperiment

func (s *Store) CreateExperiment(ctx context.Context, e *Experiment) (int64, error)

CreateExperiment inserts a new experiment and returns its ID.

func (*Store) CreateFinding

func (s *Store) CreateFinding(ctx context.Context, f *Finding) (int64, error)

CreateFinding inserts a new finding and returns its ID.

func (*Store) CreateFindingMatch

func (s *Store) CreateFindingMatch(ctx context.Context, m *FindingMatch) (int64, error)

CreateFindingMatch inserts a new finding match and returns its ID. The Go field FindingMatch.AnnotationID lands in the evidence_id column — migration 010 renamed it, evidence IDs inherit the old annotation ID space, so the value round-trips unchanged.

func (*Store) CreateProject

func (s *Store) CreateProject(ctx context.Context, p *CorpusProject) (int64, error)

CreateProject inserts a new corpus project and returns its ID.

func (*Store) CreateRun

func (s *Store) CreateRun(ctx context.Context, r *Run) (int64, error)

CreateRun inserts a new run and returns its ID.

func (*Store) CreateScanner

func (s *Store) CreateScanner(ctx context.Context, sc *Scanner) (int64, error)

CreateScanner inserts a new scanner and returns its ID.

func (*Store) CreateVulnerability

func (s *Store) CreateVulnerability(ctx context.Context, v *Vulnerability) (int64, error)

func (*Store) DeleteAnnotation

func (s *Store) DeleteAnnotation(ctx context.Context, id int64) error

DeleteAnnotation removes one evidence row. If it was the vuln's only evidence, the vuln goes too — a vulnerability with no observable location is meaningless. If other evidence remains, the vuln stays and only this location is removed.

func (*Store) DeleteAnnotationGroup

func (s *Store) DeleteAnnotationGroup(ctx context.Context, id int64) error

func (*Store) DeleteAnnotationsByProject

func (s *Store) DeleteAnnotationsByProject(ctx context.Context, projectID int64) (int64, error)

DeleteAnnotationsByProject removes everything. Under the hood this is DeleteVulnerabilitiesByProject — the cascade takes evidence, cwes, and annotators with it. Returns the evidence-row count (not the vuln count) because callers expect "number of annotations deleted."

func (*Store) DeleteDisposition

func (s *Store) DeleteDisposition(ctx context.Context, id int64) error

DeleteDisposition removes a disposition by ID.

func (*Store) DeleteExperiment

func (s *Store) DeleteExperiment(ctx context.Context, id int64) error

DeleteExperiment removes an experiment by ID. Cascade deletes experiment_scanners and experiment_projects.

func (*Store) DeleteFinding

func (s *Store) DeleteFinding(ctx context.Context, id int64) error

DeleteFinding removes a finding by ID. Finding matches are cascade deleted.

func (*Store) DeleteProject

func (s *Store) DeleteProject(ctx context.Context, id int64) error

DeleteProject removes a project by ID. Annotations are cascade deleted.

func (*Store) DeleteRun

func (s *Store) DeleteRun(ctx context.Context, id int64) error

DeleteRun removes a run by ID. Findings are cascade deleted.

func (*Store) DeleteScanner

func (s *Store) DeleteScanner(ctx context.Context, id int64) error

DeleteScanner removes a scanner by ID.

func (*Store) DeleteVulnerabilitiesByProject

func (s *Store) DeleteVulnerabilitiesByProject(ctx context.Context, projectID int64) (int64, error)

func (*Store) DeleteVulnerability

func (s *Store) DeleteVulnerability(ctx context.Context, id int64) error

func (*Store) GetAnnotation

func (s *Store) GetAnnotation(ctx context.Context, id int64) (*Annotation, error)

func (*Store) GetAnnotationGroup

func (s *Store) GetAnnotationGroup(ctx context.Context, id int64) (*AnnotationGroup, error)

GetAnnotationGroup synthesizes a group from a multi-evidence vuln. The "group ID" is the vuln ID. Single-evidence vulns return ErrNotFound — they're not groups.

func (*Store) GetAnnotationSetByHash

func (s *Store) GetAnnotationSetByHash(ctx context.Context, hash string) (*AnnotationSet, error)

func (*Store) GetDisposition

func (s *Store) GetDisposition(ctx context.Context, id int64) (*FindingDisposition, error)

GetDisposition retrieves a disposition by ID.

func (*Store) GetDispositionByFinding

func (s *Store) GetDispositionByFinding(ctx context.Context, findingID int64) (*FindingDisposition, error)

GetDispositionByFinding retrieves a disposition by finding ID.

func (*Store) GetExperiment

func (s *Store) GetExperiment(ctx context.Context, id int64) (*Experiment, error)

GetExperiment retrieves an experiment by ID.

func (*Store) GetExperimentByName

func (s *Store) GetExperimentByName(ctx context.Context, name string) (*Experiment, error)

GetExperimentByName retrieves an experiment by name.

func (*Store) GetFinding

func (s *Store) GetFinding(ctx context.Context, id int64) (*Finding, error)

GetFinding returns a single finding by ID.

func (*Store) GetProject

func (s *Store) GetProject(ctx context.Context, id int64) (*CorpusProject, error)

GetProject retrieves a project by ID.

func (*Store) GetProjectByName

func (s *Store) GetProjectByName(ctx context.Context, name string) (*CorpusProject, error)

GetProjectByName retrieves a project by its unique name.

func (*Store) GetRun

func (s *Store) GetRun(ctx context.Context, id int64) (*Run, error)

GetRun retrieves a run by ID.

func (*Store) GetScanner

func (s *Store) GetScanner(ctx context.Context, id int64) (*Scanner, error)

GetScanner retrieves a scanner by ID.

func (*Store) GetScannerByName

func (s *Store) GetScannerByName(ctx context.Context, name string) (*Scanner, error)

GetScannerByName retrieves the first scanner matching a name (newest version).

func (*Store) GetScannerByNameVersion

func (s *Store) GetScannerByNameVersion(ctx context.Context, name, version string) (*Scanner, error)

GetScannerByNameVersion retrieves a scanner by its unique name+version combination.

func (*Store) GetVulnerability

func (s *Store) GetVulnerability(ctx context.Context, id int64) (*Vulnerability, error)

func (*Store) GetVulnerabilityByName

func (s *Store) GetVulnerabilityByName(ctx context.Context, projectID int64, name string) (*Vulnerability, error)

GetVulnerabilityByName looks up a vulnerability by its name within a project. Names are unique per project by convention, not constraint — if duplicates exist, the oldest wins. Used by triage --attach-to.

func (*Store) ListAllGroupMembersByProject

func (s *Store) ListAllGroupMembersByProject(ctx context.Context, projectID int64) ([]AnnotationGroupMember, error)

ListAllGroupMembersByProject is what the scorer hash reads. Synthesized from multi-evidence vulns: each evidence row becomes a "member" of its vuln-as-group.

func (*Store) ListAnnotationGroupsByProject

func (s *Store) ListAnnotationGroupsByProject(ctx context.Context, projectID int64) ([]AnnotationGroup, error)

ListAnnotationGroupsByProject returns vulns with >1 evidence row.

func (*Store) ListAnnotationSetsByProject

func (s *Store) ListAnnotationSetsByProject(ctx context.Context, projectID int64) ([]AnnotationSet, error)

func (*Store) ListAnnotationsByProject

func (s *Store) ListAnnotationsByProject(ctx context.Context, projectID int64) ([]Annotation, error)

func (*Store) ListDispositionsByRun

func (s *Store) ListDispositionsByRun(ctx context.Context, runID int64) ([]FindingDisposition, error)

ListDispositionsByRun returns all dispositions for findings in a given run. Returns an empty slice (not nil) if none exist.

func (*Store) ListEvidenceByProject

func (s *Store) ListEvidenceByProject(ctx context.Context, projectID int64) ([]Evidence, error)

func (*Store) ListEvidenceByVuln

func (s *Store) ListEvidenceByVuln(ctx context.Context, vulnID int64) ([]Evidence, error)

func (*Store) ListExperimentProjects

func (s *Store) ListExperimentProjects(ctx context.Context, experimentID int64) ([]CorpusProject, error)

ListExperimentProjects returns all projects linked to an experiment. Returns an empty slice (not nil) if no projects are linked.

func (*Store) ListExperimentScanners

func (s *Store) ListExperimentScanners(ctx context.Context, experimentID int64) ([]Scanner, error)

ListExperimentScanners returns all scanners linked to an experiment. Returns an empty slice (not nil) if no scanners are linked.

func (*Store) ListExperiments

func (s *Store) ListExperiments(ctx context.Context) ([]Experiment, error)

ListExperiments returns all experiments. Returns an empty slice (not nil) if none exist.

func (*Store) ListFindingMatchesByRun

func (s *Store) ListFindingMatchesByRun(ctx context.Context, runID int64) ([]FindingMatch, error)

ListFindingMatchesByRun returns all finding matches for a run. Returns an empty slice (not nil) if none exist.

func (*Store) ListFindingsByRun

func (s *Store) ListFindingsByRun(ctx context.Context, runID int64) ([]Finding, error)

ListFindingsByRun returns all findings for a run. Returns an empty slice (not nil) if none exist.

func (*Store) ListGroupMembers

func (s *Store) ListGroupMembers(ctx context.Context, groupID int64) ([]AnnotationGroupMember, error)

ListGroupMembers returns evidence rows for a multi-evidence vuln. GroupID == vuln_id, AnnotationID == evidence_id.

func (*Store) ListGroupsByAnnotation

func (s *Store) ListGroupsByAnnotation(ctx context.Context, annotationID int64) ([]AnnotationGroup, error)

ListGroupsByAnnotation returns the "group" (vuln) an evidence row belongs to — but only if that vuln has siblings. Solo evidence belongs to no group in compat terms.

func (*Store) ListPendingRuns

func (s *Store) ListPendingRuns(ctx context.Context, experimentID int64) ([]Run, error)

ListPendingRuns returns all pending or failed runs for an experiment (for resume). Returns an empty slice (not nil) if none exist.

func (*Store) ListProjects

func (s *Store) ListProjects(ctx context.Context) ([]CorpusProject, error)

ListProjects returns all projects. Returns an empty slice (not nil) if none exist.

func (*Store) ListRunsByExperiment

func (s *Store) ListRunsByExperiment(ctx context.Context, experimentID int64) ([]Run, error)

ListRunsByExperiment returns all runs for an experiment. Returns an empty slice (not nil) if none exist.

func (*Store) ListRunsByProject

func (s *Store) ListRunsByProject(ctx context.Context, projectID int64) ([]Run, error)

ListRunsByProject returns all runs for a project across all scanners and experiments. Used by rescore to enumerate everything that needs re-matching when the project's ground truth changes.

func (*Store) ListRunsByScannerProject

func (s *Store) ListRunsByScannerProject(ctx context.Context, scannerID, projectID int64) ([]Run, error)

ListRunsByScannerProject returns all runs for a scanner/project combination. Returns an empty slice (not nil) if none exist.

func (*Store) ListSatisfiedVulns

func (s *Store) ListSatisfiedVulns(ctx context.Context, runID, projectID int64) ([]Vulnerability, error)

ListSatisfiedVulns returns vulnerabilities where at least one evidence row was matched by a finding in this run. These are the TPs (valid) or matched-FPs (invalid) under vulnerability-level accounting.

func (*Store) ListScanners

func (s *Store) ListScanners(ctx context.Context) ([]Scanner, error)

ListScanners returns all scanners. Returns an empty slice (not nil) if none exist.

func (*Store) ListUnmatchedAnnotations

func (s *Store) ListUnmatchedAnnotations(ctx context.Context, runID, projectID int64) ([]Annotation, error)

ListUnmatchedAnnotations returns evidence rows that have no match for a given run+project. Pre-010 this was per-annotation; now it's per-evidence, which is the same thing via the compat shim. Callers still computing metrics from this (reports, detail views) get the old per-location counting. The headline compare flow uses ListUnsatisfiedVulns instead.

func (*Store) ListUnmatchedFindings

func (s *Store) ListUnmatchedFindings(ctx context.Context, runID int64) ([]Finding, error)

ListUnmatchedFindings returns findings that have no match entry (false positives). Returns an empty slice (not nil) if none exist.

func (*Store) ListUnsatisfiedVulns

func (s *Store) ListUnsatisfiedVulns(ctx context.Context, runID, projectID int64) ([]Vulnerability, error)

ListUnsatisfiedVulns returns vulnerabilities where NO evidence row was matched. Valid ones are FNs; invalid ones are TNs. This plus ListSatisfiedVulns plus ListUnmatchedFindings is everything ComputeVulnMetrics needs.

func (*Store) ListVulnAnnotatorsByProject

func (s *Store) ListVulnAnnotatorsByProject(ctx context.Context, projectID int64) (map[int64][]string, error)

ListVulnAnnotatorsByProject returns the annotator list per vulnerability for a project. Map[vulnID][]annotator — mirror of ListVulnCWEs, used by the exporter to reconstitute the annotated_by array.

func (*Store) ListVulnCWEs

func (s *Store) ListVulnCWEs(ctx context.Context, projectID int64) (map[int64][]string, error)

ListVulnCWEs returns the acceptable CWE set per vulnerability for a project. Map[vulnID][]cweString — the matcher turns these into a normalized-int set and checks finding CWEs against it.

func (*Store) ListVulnerabilitiesByProject

func (s *Store) ListVulnerabilitiesByProject(ctx context.Context, projectID int64) ([]Vulnerability, error)

func (*Store) Migrate

func (s *Store) Migrate() error

Migrate runs all pending database migrations.

func (*Store) MigrateDown

func (s *Store) MigrateDown() error

MigrateDown rolls back all database migrations.

func (*Store) RecordAnnotationSet

func (s *Store) RecordAnnotationSet(ctx context.Context, set *AnnotationSet) (int64, error)

func (*Store) RemoveAnnotationFromGroup

func (s *Store) RemoveAnnotationFromGroup(ctx context.Context, groupID, annotationID int64) error

func (*Store) RemoveProjectFromExperiment

func (s *Store) RemoveProjectFromExperiment(ctx context.Context, experimentID, projectID int64) error

RemoveProjectFromExperiment unlinks a project from an experiment.

func (*Store) RemoveScannerFromExperiment

func (s *Store) RemoveScannerFromExperiment(ctx context.Context, experimentID, scannerID int64) error

RemoveScannerFromExperiment unlinks a scanner from an experiment.

func (*Store) StampRunScorer

func (s *Store) StampRunScorer(ctx context.Context, runID int64, matcherVersion, annotationHash string) error

StampRunScorer records which matcher version and annotation set produced this run's finding_matches rows. Called by analysis.MatchRun immediately before matching — not by the experiment executor — because the scorer that matters is the one that wrote the matches, not the one that was current when the scanner ran. Re-scoring after clearing finding_matches re-stamps.

func (*Store) UpdateAnnotation

func (s *Store) UpdateAnnotation(ctx context.Context, a *Annotation) error

UpdateAnnotation writes through to both the evidence row (location, category, severity) and its parent vuln (status, description). The CWE and annotator fields replace the vuln's FIRST entry — callers going through this shim are thinking in single-CWE terms anyway.

If the evidence belongs to a multi-evidence vuln, the status and description changes affect the whole vuln. That's arguably surprising, but it's what "update this annotation's status" meant under the old group semantics too (groups never had their own status; they inherited from members).

func (*Store) UpdateRunStatus

func (s *Store) UpdateRunStatus(ctx context.Context, id int64, status RunStatus, startedAt, completedAt sql.NullTime, durationMs, memoryPeakBytes sql.NullInt64, sarifPath, logPath, errorMessage sql.NullString) error

UpdateRunStatus updates the status and related fields of a run.

func (*Store) VulnConsensus

func (s *Store) VulnConsensus(ctx context.Context, projectID int64) (map[int64]int, error)

VulnConsensus returns how many distinct annotators agree each vulnerability exists. 1 = single annotator's call; 3 = strong consensus. Compare's --min-consensus filter reads this.

type VulnWithDetail

type VulnWithDetail struct {
	Vulnerability
	Evidence   []Evidence
	CWEs       []string
	Annotators []string
}

VulnWithDetail bundles a vulnerability with its evidence locations, acceptable CWEs, and annotator list — everything needed to score it without further round trips. This is what the matcher and the importer want; the flat types above are for CRUD.

type Vulnerability

type Vulnerability struct {
	ID          int64
	ProjectID   int64
	Name        string
	Description sql.NullString
	// Criticality tiers findings for separate recall reporting. A tool
	// that misses a 'must' is worse than one that misses a 'may' at the
	// same overall recall.
	Criticality string // must | should | may
	Status      string // valid | invalid | disputed
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

Vulnerability is the unit of ground truth. One vulnerability may be evidenced at many locations (vuln_evidence rows) and may be correctly described by many CWEs (vuln_cwes rows). A scanner finding matches the vulnerability if it matches any evidence location with any acceptable CWE; the vulnerability is then satisfied and scores one TP regardless of how many evidence locations were hit.

Jump to

Keyboard shortcuts

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