Skip to content

Commit 3d710b0

Browse files
committed
Embed shared package coordinates
Embed Coordinates in both Dependency and Package so their shared identity fields remain explicit while preserving distinct domain models. Add an ID to Package for registry keys or database identifiers, defaulting registry-created packages to their PURL when no explicit ID is provided. Rewrite SDK and internal composite literals to populate the embedded Coordinates field directly and cover the registry ID default with a unit test.
1 parent dea8d0f commit 3d710b0

77 files changed

Lines changed: 641 additions & 665 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

internal/analyzers/govulncheck/analyzer_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,10 @@ func newGoModuleDir(t *testing.T) string {
3939
// (keyed by the dependency's PURL) carries the supplied vulnerabilities.
4040
func newGoGraph(moduleDir string, vulns ...model.Vulnerability) (*model.Graph, *model.PackageRegistry) {
4141
g := model.New()
42-
dep := model.NewDependency(model.Dependency{
43-
Name: "example.com/lib",
42+
dep := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "example.com/lib",
4443
Version: "v1.0.0",
4544
Ecosystem: "go",
46-
PackageManager: "gomod",
47-
Locations: []model.PackageLocation{{RealPath: filepath.Join(moduleDir, "go.sum")}},
45+
PackageManager: "gomod"}, Locations: []model.PackageLocation{{RealPath: filepath.Join(moduleDir, "go.sum")}},
4846
})
4947
purl := model.CanonicalPackageURLFromDependency(dep)
5048
dep.PackageRef = purl
@@ -215,7 +213,7 @@ func TestAnalyzerApplicableRequiresGoVulns(t *testing.T) {
215213
// build a graph+registry where dep's package carries the given vulns.
216214
build := func(name, ecosystem string, vulns ...model.Vulnerability) (*model.Graph, *model.PackageRegistry) {
217215
g := model.New()
218-
dep := model.NewDependency(model.Dependency{Name: name, Ecosystem: model.Ecosystem(ecosystem)})
216+
dep := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: name, Ecosystem: model.Ecosystem(ecosystem)}})
219217
purl := model.CanonicalPackageURLFromDependency(dep)
220218
dep.PackageRef = purl
221219
_ = g.AddNode(dep)

internal/analyzers/govulncheck/testdata_test.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@ func goFixture(parts ...string) string {
2323
func TestDiscoverModuleRootsFromTestdata(t *testing.T) {
2424
root := goFixture("module")
2525
g := model.New()
26-
pkg := model.NewDependency(model.Dependency{
27-
Name: "example.com/lib",
28-
Ecosystem: model.EcosystemGo,
29-
Locations: []model.PackageLocation{{RealPath: filepath.Join(root, "nested", "file.go")}},
26+
pkg := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "example.com/lib",
27+
Ecosystem: model.EcosystemGo}, Locations: []model.PackageLocation{{RealPath: filepath.Join(root, "nested", "file.go")}},
3028
})
3129
if err := g.AddNode(pkg); err != nil {
3230
t.Fatal(err)
@@ -120,10 +118,9 @@ func TestGovulncheckFailureReasons(t *testing.T) {
120118
func TestGovulncheckAnalyzerMarksUnknownWithoutModuleRoot(t *testing.T) {
121119
const purl = "pkg:golang/example.com/lib"
122120
g := model.New()
123-
pkg := model.NewDependency(model.Dependency{
124-
Name: "example.com/lib",
121+
pkg := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "example.com/lib",
125122
Ecosystem: model.EcosystemGo,
126-
PURL: purl,
123+
PURL: purl},
127124
})
128125
if err := g.AddNode(pkg); err != nil {
129126
t.Fatal(err)
@@ -154,7 +151,7 @@ func TestGovulncheckLookupFindingAndImportedModuleAliases(t *testing.T) {
154151
t.Fatalf("lookupFinding(%+v) missed", vuln)
155152
}
156153
}
157-
pkg := model.NewDependency(model.Dependency{Name: "example.com/lib"})
154+
pkg := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "example.com/lib"}})
158155
if !packageImportedByModule(pkg, map[string]struct{}{"example.com/lib": {}}) {
159156
t.Fatal("package name was not matched against imported module set")
160157
}

internal/analyzers/jsreach/analyzer_test.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,11 @@ func newNPMProjectDir(t *testing.T) string {
4848
// Returns the dependency node.
4949
func addNPMDep(t *testing.T, g *model.Graph, reg *model.PackageRegistry, projectDir, org, name, version string, vulns ...model.Vulnerability) *model.Dependency {
5050
t.Helper()
51-
dep := model.NewDependency(model.Dependency{
52-
Name: name,
51+
dep := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: name,
5352
Org: org,
5453
Version: version,
5554
Ecosystem: "npm",
56-
PackageManager: "npm",
57-
Locations: []model.PackageLocation{{RealPath: filepath.Join(projectDir, "package-lock.json")}},
55+
PackageManager: "npm"}, Locations: []model.PackageLocation{{RealPath: filepath.Join(projectDir, "package-lock.json")}},
5856
})
5957
purl := model.CanonicalPackageURLFromDependency(dep)
6058
dep.PackageRef = purl
@@ -178,7 +176,7 @@ func TestAnalyzerApplicableRequiresNPMVulns(t *testing.T) {
178176

179177
// go package with vuln → not applicable
180178
g, reg := newSeed()
181-
goDep := model.NewDependency(model.Dependency{Name: "lib", Ecosystem: "go"})
179+
goDep := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "lib", Ecosystem: "go"}})
182180
goDep.PackageRef = model.CanonicalPackageURLFromDependency(goDep)
183181
_ = g.AddNode(goDep)
184182
reg.Ensure(goDep.PackageRef).Vulnerabilities = []model.Vulnerability{{ID: "x"}}
@@ -264,8 +262,8 @@ func TestAnalyzerDoesNotExpandThroughUnimportedRoots(t *testing.T) {
264262

265263
func TestComputeReachablePackageHopsHandlesCycles(t *testing.T) {
266264
g := model.New()
267-
a := model.NewDependency(model.Dependency{Name: "a", Version: "1.0.0", Ecosystem: "npm"})
268-
b := model.NewDependency(model.Dependency{Name: "b", Version: "1.0.0", Ecosystem: "npm"})
265+
a := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "a", Version: "1.0.0", Ecosystem: "npm"}})
266+
b := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "b", Version: "1.0.0", Ecosystem: "npm"}})
269267
if err := g.AddNode(a); err != nil {
270268
t.Fatal(err)
271269
}

internal/analyzers/jsreach/runner_testdata_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestJSDescriptorAndRunnerResult(t *testing.T) {
7575
func TestJSStandaloneApplyRunnerResult(t *testing.T) {
7676
const purl = "pkg:npm/lodash"
7777
g := model.New()
78-
pkg := model.NewDependency(model.Dependency{Name: "lodash", Ecosystem: "npm", PURL: purl})
78+
pkg := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "lodash", Ecosystem: "npm", PURL: purl}})
7979
if err := g.AddNode(pkg); err != nil {
8080
t.Fatal(err)
8181
}

internal/analyzers/jsreach/workspace_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ func TestAnalyzerTraversesConsumedWorkspaceMembers(t *testing.T) {
109109
reg := model.NewPackageRegistry()
110110
lodashPURL := "pkg:npm/lodash@1"
111111
leftPadPURL := "pkg:npm/left-pad@1"
112-
lodash := model.NewDependency(model.Dependency{Name: "lodash", Version: "1", Ecosystem: "npm", PURL: lodashPURL})
113-
leftPad := model.NewDependency(model.Dependency{Name: "left-pad", Version: "1", Ecosystem: "npm", PURL: leftPadPURL})
112+
lodash := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "lodash", Version: "1", Ecosystem: "npm", PURL: lodashPURL}})
113+
leftPad := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "left-pad", Version: "1", Ecosystem: "npm", PURL: leftPadPURL}})
114114
reg.Ensure(lodashPURL).Vulnerabilities = []model.Vulnerability{{ID: "lodash"}}
115115
reg.Ensure(leftPadPURL).Vulnerabilities = []model.Vulnerability{{ID: "left-pad"}}
116116
_ = g.AddNode(lodash)
@@ -157,7 +157,7 @@ func newNPMGraph(t *testing.T, name, version string, vulns ...model.Vulnerabilit
157157
t.Helper()
158158
purl := "pkg:npm/" + name + "@" + version
159159
g := model.New()
160-
dep := model.NewDependency(model.Dependency{Name: name, Version: version, Ecosystem: "npm", PURL: purl})
160+
dep := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: name, Version: version, Ecosystem: "npm", PURL: purl}})
161161
if err := g.AddNode(dep); err != nil {
162162
t.Fatalf("add node: %v", err)
163163
}

internal/analyzers/jsreach/workspace_testdata_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,8 @@ func TestDiscoverWorkspaceHierarchiesFromTestdata(t *testing.T) {
8080
func TestDiscoverProjectRootsDeduplicatesGraphAndTargetSources(t *testing.T) {
8181
root := workspaceFixture("npm-array")
8282
g := model.New()
83-
pkg := model.NewDependency(model.Dependency{
84-
Name: "lodash",
85-
Ecosystem: "npm",
86-
Locations: []model.PackageLocation{{RealPath: filepath.Join(root, "package-lock.json")}},
83+
pkg := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "lodash",
84+
Ecosystem: "npm"}, Locations: []model.PackageLocation{{RealPath: filepath.Join(root, "package-lock.json")}},
8785
})
8886
if err := g.AddNode(pkg); err != nil {
8987
t.Fatal(err)
@@ -198,8 +196,8 @@ func TestAnalyzerBuiltInRunnerTraversesWorkspaceTestdata(t *testing.T) {
198196
reg := model.NewPackageRegistry()
199197
lodashPURL := "pkg:npm/lodash@1"
200198
leftPadPURL := "pkg:npm/left-pad@1"
201-
lodash := model.NewDependency(model.Dependency{Name: "lodash", Version: "1", Ecosystem: "npm", PURL: lodashPURL})
202-
leftPad := model.NewDependency(model.Dependency{Name: "left-pad", Version: "1", Ecosystem: "npm", PURL: leftPadPURL})
199+
lodash := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "lodash", Version: "1", Ecosystem: "npm", PURL: lodashPURL}})
200+
leftPad := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "left-pad", Version: "1", Ecosystem: "npm", PURL: leftPadPURL}})
203201
reg.Ensure(lodashPURL).Vulnerabilities = []model.Vulnerability{{ID: "lodash"}}
204202
reg.Ensure(leftPadPURL).Vulnerabilities = []model.Vulnerability{{ID: "left-pad"}}
205203
if err := g.AddNode(lodash); err != nil {

internal/analyzers/jvmreach/analyzer_test.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,11 @@ func newSeed() (*model.Graph, *model.PackageRegistry) {
5757
// package keyed by the dependency PURL carrying those vulnerabilities.
5858
func addJVMDep(t *testing.T, g *model.Graph, reg *model.PackageRegistry, projectDir, group, artifact, version string, vulns ...model.Vulnerability) *model.Dependency {
5959
t.Helper()
60-
dep := model.NewDependency(model.Dependency{
61-
Name: artifact,
60+
dep := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: artifact,
6261
Org: group,
6362
Version: version,
6463
Ecosystem: model.EcosystemMaven,
65-
PackageManager: "maven",
66-
Locations: []model.PackageLocation{{RealPath: filepath.Join(projectDir, "pom.xml")}},
64+
PackageManager: "maven"}, Locations: []model.PackageLocation{{RealPath: filepath.Join(projectDir, "pom.xml")}},
6765
})
6866
purl := model.CanonicalPackageURLFromDependency(dep)
6967
dep.PackageRef = purl
@@ -194,8 +192,8 @@ func TestAnalyzerMarksTransitiveDepReachable(t *testing.T) {
194192

195193
func TestComputeReachablePackageHopsHandlesCycles(t *testing.T) {
196194
g := model.New()
197-
a := model.NewDependency(model.Dependency{Name: "a", Org: "g", Version: "1", Ecosystem: model.EcosystemMaven})
198-
b := model.NewDependency(model.Dependency{Name: "b", Org: "g", Version: "1", Ecosystem: model.EcosystemMaven})
195+
a := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "a", Org: "g", Version: "1", Ecosystem: model.EcosystemMaven}})
196+
b := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "b", Org: "g", Version: "1", Ecosystem: model.EcosystemMaven}})
199197
if err := g.AddNode(a); err != nil {
200198
t.Fatal(err)
201199
}
@@ -221,7 +219,7 @@ func TestAnalyzerApplicableRequiresJVMVulns(t *testing.T) {
221219
a := Analyzer{}
222220

223221
g, reg := newSeed()
224-
pyDep := model.NewDependency(model.Dependency{Name: "requests", Ecosystem: model.EcosystemPython})
222+
pyDep := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "requests", Ecosystem: model.EcosystemPython}})
225223
pyDep.PackageRef = model.CanonicalPackageURLFromDependency(pyDep)
226224
_ = g.AddNode(pyDep)
227225
reg.Ensure(pyDep.PackageRef).Vulnerabilities = []model.Vulnerability{{ID: "x"}}

internal/analyzers/jvmreach/modules_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ func TestAnalyzerTraversesConsumedMavenModules(t *testing.T) {
9696
reg := model.NewPackageRegistry()
9797
jacksonPURL := "pkg:maven/com.fasterxml.jackson.core/jackson-databind@1"
9898
log4jPURL := "pkg:maven/org.apache.logging.log4j/log4j-core@1"
99-
jackson := model.NewDependency(model.Dependency{Name: "jackson-databind", Org: "com.fasterxml.jackson.core", Version: "1", Ecosystem: "maven", PURL: jacksonPURL})
100-
log4j := model.NewDependency(model.Dependency{Name: "log4j-core", Org: "org.apache.logging.log4j", Version: "1", Ecosystem: "maven", PURL: log4jPURL})
99+
jackson := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "jackson-databind", Org: "com.fasterxml.jackson.core", Version: "1", Ecosystem: "maven", PURL: jacksonPURL}})
100+
log4j := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "log4j-core", Org: "org.apache.logging.log4j", Version: "1", Ecosystem: "maven", PURL: log4jPURL}})
101101
reg.Ensure(jacksonPURL).Vulnerabilities = []model.Vulnerability{{ID: "jackson"}}
102102
reg.Ensure(log4jPURL).Vulnerabilities = []model.Vulnerability{{ID: "log4j"}}
103103
_ = g.AddNode(jackson)

internal/analyzers/jvmreach/modules_testdata_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,9 @@ func TestGradleIncludedProjectPaths(t *testing.T) {
128128
func TestDiscoverProjectRootsDeduplicatesGraphAndTargetSources(t *testing.T) {
129129
root := moduleFixture("maven-reactor")
130130
g := model.New()
131-
pkg := model.NewDependency(model.Dependency{
132-
Name: "jackson-databind",
131+
pkg := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "jackson-databind",
133132
Org: "com.fasterxml.jackson.core",
134-
Ecosystem: "maven",
135-
Locations: []model.PackageLocation{{RealPath: filepath.Join(root, "app", "pom.xml")}},
133+
Ecosystem: "maven"}, Locations: []model.PackageLocation{{RealPath: filepath.Join(root, "app", "pom.xml")}},
136134
})
137135
if err := g.AddNode(pkg); err != nil {
138136
t.Fatal(err)
@@ -233,8 +231,8 @@ func TestAnalyzerBuiltInRunnerTraversesMavenReactorTestdata(t *testing.T) {
233231
reg := model.NewPackageRegistry()
234232
jacksonPURL := "pkg:maven/com.fasterxml.jackson.core/jackson-databind@1"
235233
log4jPURL := "pkg:maven/org.apache.logging.log4j/log4j-core@1"
236-
jackson := model.NewDependency(model.Dependency{Name: "jackson-databind", Org: "com.fasterxml.jackson.core", Version: "1", Ecosystem: "maven", PURL: jacksonPURL})
237-
log4j := model.NewDependency(model.Dependency{Name: "log4j-core", Org: "org.apache.logging.log4j", Version: "1", Ecosystem: "maven", PURL: log4jPURL})
234+
jackson := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "jackson-databind", Org: "com.fasterxml.jackson.core", Version: "1", Ecosystem: "maven", PURL: jacksonPURL}})
235+
log4j := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "log4j-core", Org: "org.apache.logging.log4j", Version: "1", Ecosystem: "maven", PURL: log4jPURL}})
238236
reg.Ensure(jacksonPURL).Vulnerabilities = []model.Vulnerability{{ID: "jackson"}}
239237
reg.Ensure(log4jPURL).Vulnerabilities = []model.Vulnerability{{ID: "log4j"}}
240238
if err := g.AddNode(jackson); err != nil {

internal/analyzers/jvmreach/runner_testdata_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,10 @@ func TestJVMDescriptorAndRunnerResult(t *testing.T) {
6565
func TestJVMStandaloneApplyRunnerResult(t *testing.T) {
6666
const purl = "pkg:maven/com.fasterxml.jackson.core/jackson-databind"
6767
g := model.New()
68-
pkg := model.NewDependency(model.Dependency{
69-
Name: "jackson-databind",
68+
pkg := model.NewDependency(model.Dependency{Coordinates: model.Coordinates{Name: "jackson-databind",
7069
Org: "com.fasterxml.jackson.core",
7170
Ecosystem: model.EcosystemMaven,
72-
PURL: purl,
71+
PURL: purl},
7372
})
7473
if err := g.AddNode(pkg); err != nil {
7574
t.Fatal(err)

0 commit comments

Comments
 (0)