exp,internal/govulncheck: add govulncheck API

An API is defined for internal/govulncheck.

The API in exp/govulncheck is updated to use internal/govulncheck.Config
and internal/govulncheck.Source.

For golang/go#56042

Change-Id: Ibab2fae0685166e7712b355e2c7c2ab0b4d50c6c
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/440219
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Julie Qiu <julie@golang.org>
diff --git a/exp/govulncheck/govulncheck.go b/exp/govulncheck/govulncheck.go
index 12fa6b6..ee36839 100644
--- a/exp/govulncheck/govulncheck.go
+++ b/exp/govulncheck/govulncheck.go
@@ -2,21 +2,35 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package govulncheck has experimental govulncheck API.
+// Package govulncheck provides an experimental govulncheck API.
 package govulncheck
 
-import (
-	"context"
+import "golang.org/x/vuln/internal/govulncheck"
 
-	"golang.org/x/vuln/internal/govulncheck"
+// Source reports vulnerabilities that affect the analyzed packages.
+var Source = govulncheck.Source
+
+type (
+	// Config is the configuration for Main.
+	Config = govulncheck.Config
+
+	// Result is the result of executing Source.
+	Result = govulncheck.Result
+
+	// Vuln represents a single OSV entry.
+	Vuln = govulncheck.Vuln
+
+	// Module represents a specific vulnerability relevant to a
+	// single module or package.
+	Module = govulncheck.Module
+
+	// Package is a Go package with known vulnerable symbols.
+	Package = govulncheck.Package
+
+	// CallStacks contains a representative call stack for each
+	// vulnerable symbol that is called.
+	CallStack = govulncheck.CallStack
+
+	// StackFrame represents a call stack entry.
+	StackFrame = govulncheck.StackFrame
 )
-
-// Config is the configuration for Main.
-type Config = govulncheck.LegacyConfig
-
-// Main is the main function for the govulncheck command line tool.
-func Main(cfg Config) error {
-	ctx := context.Background()
-	_, err := govulncheck.LegacyRun(ctx, cfg)
-	return err
-}
diff --git a/internal/govulncheck/cache.go b/internal/govulncheck/cache.go
index 5ce73e4..922a694 100644
--- a/internal/govulncheck/cache.go
+++ b/internal/govulncheck/cache.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package govulncheck supports the govulncheck command.
 package govulncheck
 
 import (
diff --git a/internal/govulncheck/result.go b/internal/govulncheck/result.go
index 16b2359..f6916f7 100644
--- a/internal/govulncheck/result.go
+++ b/internal/govulncheck/result.go
@@ -1,10 +1,153 @@
 // Copyright 2022 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
+
+// Package govulncheck provides functionality to support the govulncheck command.
 package govulncheck
 
-// Result is contains output information for govulncheck.
-//
-// TODO(https://go.dev/issue/56042): this API is a work in progress.
+import (
+	"go/token"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/client"
+	"golang.org/x/vuln/osv"
+)
+
+// LoadMode is the level of information needed for each package
+// for running golang.org/x/tools/go/packages.Load.
+var LoadMode = packages.NeedName | packages.NeedImports | packages.NeedTypes |
+	packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedDeps |
+	packages.NeedModule
+
+// Config is used for configuring the output of govulncheck.
+type Config struct {
+	// Client is the client used to make requests to a vulnerability
+	// database(s). If nil, a default client is constructed that makes requests
+	// to vuln.go.dev.
+	Client client.Client
+
+	// GoVersion specifies the Go version used when analyzing source code.
+	//
+	// By default, GoVersion is the go command version found from the PATH.
+	GoVersion string
+
+	// Verbosity controls the stdout and stderr output when running Source.
+	//
+	// TODO(https://go.dev/issue/56042): make this an enum.
+	Verbosity string
+}
+
+// Result is the result of executing Source or Binary.
 type Result struct {
+	// Vulns contains all vulnerabilities that are called or imported by
+	// the analyzed module.
+	Vulns []*Vuln
+}
+
+// Vuln represents a single OSV entry.
+type Vuln struct {
+	// OSV contains all data from the OSV entry for this vulnerability.
+	OSV *osv.Entry
+
+	// Modules contains all of the modules in the OSV entry where a
+	// vulnerable package is imported by the target source code or binary.
+	//
+	// For example, a module M with two packages M/p1 and M/p2, where only p1
+	// is vulnerable, will appear in this list if and only if p1 is imported by
+	// the target source code or binary.
+	Modules []*Module
+}
+
+// IsCalled reports whether the vulnerability is called, therefore
+// affecting the target source code or binary.
+//
+// TODO(https://go.dev/issue/56042): implement
+func (v *Vuln) IsCalled() bool {
+	return false
+}
+
+// Module represents a specific vulnerability relevant to a single module.
+type Module struct {
+	// Path is the module path of the module containing the vulnerability.
+	//
+	// Importable packages in the standard library will have the path "stdlib".
+	Path string
+
+	// FoundVersion is the module version where the vulnerability was found.
+	FoundVersion string
+
+	// FixedVersion is the module version where the vulnerability was
+	// fixed. If there are multiple fixed versions in the OSV report, this will
+	// be the latest fixed version.
+	//
+	// This is empty if a fix is not available.
+	FixedVersion string
+
+	// Packages contains all the vulnerable packages in OSV entry that are
+	// imported by the target source code or binary.
+	//
+	// For example, given a module M with two packages M/p1 and M/p2, where
+	// both p1 and p2 are vulnerable, p1 and p2 will each only appear in this
+	// list they are individually imported by the target source code or binary.
+	Packages []*Package
+}
+
+// Package is a Go package with known vulnerable symbols.
+type Package struct {
+	// Path is the import path of the package containing the vulnerability.
+	Path string
+
+	// CallStacks contains a representative call stack for each
+	// vulnerable symbol that is called.
+	//
+	// For vulnerabilities found from binary analysis, only CallStack.Symbol
+	// will be provided.
+	//
+	// For non-affecting vulnerabilities reported from the source mode
+	// analysis, this will be empty.
+	CallStacks []CallStack
+}
+
+// CallStacks contains a representative call stack for a vulnerable
+// symbol.
+type CallStack struct {
+	// Symbol is the name of the detected vulnerable function
+	// or method.
+	//
+	// This follows the naming convention in the OSV report.
+	Symbol string
+
+	// Summary is a one-line description of the callstack, used by the
+	// default govulncheck mode.
+	//
+	// Example: module3.main calls github.com/shiyanhui/dht.DHT.Run
+	Summary string
+
+	// Frames contains an entry for each stack in the call stack.
+	//
+	// Frames are sorted starting from the entry point to the
+	// imported vulnerable symbol. The last frame in Frames should match
+	// Symbol.
+	Frames []*StackFrame
+}
+
+// StackFrame represents a call stack entry.
+type StackFrame struct {
+	// PackagePath is the import path.
+	PkgPath string
+
+	// FuncName is the function name.
+	FuncName string
+
+	// RecvName is the receiver name, if the symbol is a
+	// method.
+	//
+	// The client can create the final symbol name by
+	// prepending RecvName to FuncName.
+	RecvName string
+
+	// Position describes an arbitrary source position
+	// including the file, line, and column location.
+	// A Position is valid if the line number is > 0.
+	Position token.Position
 }
diff --git a/internal/govulncheck/run.go b/internal/govulncheck/run.go
new file mode 100644
index 0000000..927f770
--- /dev/null
+++ b/internal/govulncheck/run.go
@@ -0,0 +1,36 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package govulncheck
+
+import (
+	"context"
+	"errors"
+	"io"
+
+	"golang.org/x/vuln/vulncheck"
+)
+
+// Source reports vulnerabilities that affect the analyzed packages.
+//
+// Vulnerabilities can be called (affecting the package, because a vulnerable
+// symbol is actually exercised) or just imported by the package
+// (likely having a non-affecting outcome).
+//
+// This function is used for source code analysis by cmd/govulncheck and
+// exp/govulncheck.
+//
+// TODO(https://go.dev/issue/56042): implement
+func Source(ctx context.Context, cfg *Config, pkgs []*vulncheck.Package) (*Result, error) {
+	return nil, errors.New("not implemented")
+}
+
+// Binary detects presence of vulnerable symbols in exe.
+//
+// This function is used for binary analysis by cmd/govulncheck.
+//
+// TODO(https://go.dev/issue/56042): implement
+func Binary(ctx context.Context, cfg *Config, exe io.ReaderAt) (*Result, error) {
+	return nil, errors.New("not implemented")
+}