Skip to content

Commit a747c3e

Browse files
committed
refactor(aibom): use shared vdb-cyclonedx AIBOM format
Move the AIBOM data model + builder out of internal/cdx into vdb-cyclonedx (v0.2.0): the detector now emits cyclonedx.AIDetections and cmd/aibom.go builds via cyclonedx.BuildAIBOM(detections, AIBOMOptions{Project}). One implementation of build/parse/validate shared with vdb-api and vdb-site. Output is unchanged (verified: CycloneDX 1.7, git metadata, @cf/ Workers AI models + evidence).
1 parent f231524 commit a747c3e

12 files changed

Lines changed: 62 additions & 457 deletions

File tree

cmd/aibom.go

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
"time"
1010

11+
cyclonedx "github.com/Vulnetix/vdb-cyclonedx"
1112
"github.com/spf13/cobra"
1213
"github.com/vulnetix/cli/v3/internal/aibom"
1314
"github.com/vulnetix/cli/v3/internal/cdx"
@@ -120,18 +121,15 @@ func runAIBOM(cmd *cobra.Command, args []string) error {
120121
}
121122

122123
// Build the CycloneDX AIBOM once — used both for cyclonedx-json output and
123-
// for the backend submission below.
124-
ctx := &cdx.ScanContext{
125-
Git: gitctx.Collect(rootPath),
126-
System: gitctx.CollectSystemInfo(),
127-
ToolVersion: version,
124+
// for the backend submission below. The format (build + validate) lives in
125+
// the shared vdb-cyclonedx module so producers and consumers agree.
126+
gitCtx := gitctx.Collect(rootPath)
127+
bomData, err := cyclonedx.BuildAIBOM(det, cyclonedx.AIBOMOptions{
128+
SpecVersion: specVersion,
128129
ToolName: "vulnetix-aibom",
129-
}
130-
bom, err := cdx.BuildAIBOM(det, specVersion, ctx)
131-
if err != nil {
132-
return err
133-
}
134-
bomData, err := bom.MarshalValidatedJSON()
130+
ToolVersion: version,
131+
Project: aibomProject(gitCtx, gitctx.CollectSystemInfo()),
132+
})
135133
if err != nil {
136134
return err
137135
}
@@ -140,7 +138,7 @@ func runAIBOM(cmd *cobra.Command, args []string) error {
140138
// fails the command, and community/unauthenticated callers are skipped (the
141139
// server would not persist their data anyway).
142140
if !noUpload {
143-
uploadAIBOM(specVersion, det, bomData, ctx.Git)
141+
uploadAIBOM(specVersion, det, bomData, gitCtx)
144142
}
145143

146144
switch outputFmt {
@@ -184,27 +182,52 @@ func detectAndUploadAIBOM(rootPath string, gitCtx *gitctx.GitContext) {
184182
if err != nil || len(det.Tools)+len(det.Libraries)+len(det.Models) == 0 {
185183
return
186184
}
187-
ctx := &cdx.ScanContext{
188-
Git: gitCtx,
189-
System: gitctx.CollectSystemInfo(),
190-
ToolVersion: version,
185+
data, err := cyclonedx.BuildAIBOM(det, cyclonedx.AIBOMOptions{
186+
SpecVersion: "1.7",
191187
ToolName: "vulnetix-aibom",
192-
}
193-
bom, err := cdx.BuildAIBOM(det, "1.7", ctx)
194-
if err != nil {
195-
return
196-
}
197-
data, err := bom.MarshalValidatedJSON()
188+
ToolVersion: version,
189+
Project: aibomProject(gitCtx, gitctx.CollectSystemInfo()),
190+
})
198191
if err != nil {
199192
return
200193
}
201194
uploadAIBOM("1.7", det, data, gitCtx)
202195
}
203196

197+
// aibomProject maps the CLI's git/system context to the shared AIBOMProject the
198+
// vdb-cyclonedx builder consumes for metadata.component and git/env properties.
199+
func aibomProject(g *gitctx.GitContext, sys *gitctx.SystemInfo) *cyclonedx.AIBOMProject {
200+
p := &cyclonedx.AIBOMProject{}
201+
if g != nil {
202+
p.Name = cdx.GitProjectName(g)
203+
p.Version = cdx.GitProjectVersion(g)
204+
p.Branch = g.CurrentBranch
205+
p.Commit = g.CurrentCommit
206+
p.CommitTimestamp = g.HeadCommitTimestamp
207+
p.CommitMessage = g.HeadCommitMessage
208+
p.CommitAuthor = g.HeadCommitAuthor
209+
p.CommitEmail = g.HeadCommitEmail
210+
p.Tags = g.HeadTags
211+
p.IsDirty = g.IsDirty
212+
p.IsWorktree = g.IsWorktree
213+
p.RepoRoot = g.RepoRootPath
214+
p.RemoteURLs = g.RemoteURLs
215+
for _, c := range g.RecentCommitters {
216+
p.RecentCommitters = append(p.RecentCommitters, cyclonedx.AIBOMContact{Name: c.Name, Email: c.Email})
217+
}
218+
}
219+
if sys != nil {
220+
p.System = &cyclonedx.AIBOMSystem{
221+
Hostname: sys.Hostname, Shell: sys.Shell, OS: sys.OS, Arch: sys.Arch, Username: sys.Username,
222+
}
223+
}
224+
return p
225+
}
226+
204227
// uploadAIBOM submits the AIBOM to POST /v2/cli.ai-bom. It is best-effort:
205228
// community/unauthenticated callers are skipped (the server does not persist
206229
// their data — see the community no-persist gate) and any error is non-fatal.
207-
func uploadAIBOM(specVersion string, det cdx.AIDetections, bomData []byte, git *gitctx.GitContext) {
230+
func uploadAIBOM(specVersion string, det cyclonedx.AIDetections, bomData []byte, git *gitctx.GitContext) {
208231
creds, err := auth.LoadCredentials()
209232
if err != nil || creds == nil || auth.IsCommunity(creds) {
210233
return
@@ -258,7 +281,7 @@ func writeAIBOMOutput(path string, data []byte) error {
258281
return nil
259282
}
260283

261-
func renderAIBOMTable(cmd *cobra.Command, det cdx.AIDetections) error {
284+
func renderAIBOMTable(cmd *cobra.Command, det cyclonedx.AIDetections) error {
262285
dctx := display.FromCommand(cmd)
263286
if dctx.IsJSON() {
264287
data, err := json.MarshalIndent(det, "", " ")

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.25.0
44

55
require (
66
github.com/Masterminds/semver/v3 v3.5.0
7-
github.com/Vulnetix/vdb-cyclonedx v0.1.0
7+
github.com/Vulnetix/vdb-cyclonedx v0.2.0
88
github.com/alecthomas/chroma/v2 v2.26.1
99
github.com/charmbracelet/bubbles v1.0.0
1010
github.com/charmbracelet/bubbletea v1.3.10

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
77
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
88
github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM=
99
github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo=
10-
github.com/Vulnetix/vdb-cyclonedx v0.1.0 h1:LI/8ypN7MabidtCcjUFCjI5CSG+WS6BfX/FxHGS/1nw=
11-
github.com/Vulnetix/vdb-cyclonedx v0.1.0/go.mod h1:0YeNSe1jhyjAZdAQ8Atkj8wZj2XzLjVXdu3P6qlTBh8=
10+
github.com/Vulnetix/vdb-cyclonedx v0.2.0 h1:edCLVlyVchkWIx9vRiST3U6hkrGG/4iHOvVob3NFhL0=
11+
github.com/Vulnetix/vdb-cyclonedx v0.2.0/go.mod h1:OdwvoW17lbz3CFqBp/csiwZJx7xat1u4zoG6GUEM8U4=
1212
github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM=
1313
github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
1414
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=

internal/aibom/detect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"strconv"
1010
"strings"
1111

12-
"github.com/vulnetix/cli/v3/internal/cdx"
12+
cdx "github.com/Vulnetix/vdb-cyclonedx"
1313
"github.com/vulnetix/cli/v3/internal/sast"
1414
)
1515

internal/aibom/detect_commits.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"github.com/go-git/go-git/v5"
88
"github.com/go-git/go-git/v5/plumbing/object"
99

10-
"github.com/vulnetix/cli/v3/internal/cdx"
10+
cdx "github.com/Vulnetix/vdb-cyclonedx"
1111
)
1212

1313
// defaultCommitScanMax bounds how many commits (from HEAD backwards) the commit

internal/aibom/detect_env.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package aibom
33
import (
44
"strings"
55

6-
"github.com/vulnetix/cli/v3/internal/cdx"
6+
cdx "github.com/Vulnetix/vdb-cyclonedx"
77
)
88

99
// detectEnv records which catalog env-var names are present in the environment.

internal/aibom/detect_files.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"regexp"
77
"strings"
88

9-
"github.com/vulnetix/cli/v3/internal/cdx"
9+
cdx "github.com/Vulnetix/vdb-cyclonedx"
1010
"github.com/vulnetix/cli/v3/internal/sast"
1111
)
1212

internal/aibom/detect_source.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package aibom
22

33
import (
4-
"github.com/vulnetix/cli/v3/internal/cdx"
4+
cdx "github.com/Vulnetix/vdb-cyclonedx"
55
"github.com/vulnetix/cli/v3/internal/sast"
66
)
77

internal/aibom/detect_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"strings"
77
"testing"
88

9-
"github.com/vulnetix/cli/v3/internal/cdx"
9+
cdx "github.com/Vulnetix/vdb-cyclonedx"
1010
)
1111

1212
func compiledCatalog(t *testing.T) *CompiledCatalog {

0 commit comments

Comments
 (0)